用UISwitch显示和隐藏UITableViewCell过快崩溃
我有一个UITableView向用户展示一些设置。 除非UISwitch处于“On”位置,否则某些单元将被隐藏。 我有以下代码:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return switchPush.on ? 6 : 1; } // Hooked to the 'Value Changed' action of the switchPush - (IBAction)togglePush:(id)sender { NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:0]; for(int i = 1; i <= 5; i++) { [indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]]; } [tableView beginUpdates]; if(switchPush.on) { [tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic]; } else { [tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic]; } [tableView endUpdates]; }
这按预期工作,直到我快速连续两次切换UISwitch(通过双击),在这种情况下,应用程序崩溃
Invalid table view update. The application has requested an update to the table view that is inconsistent with the state provided by the data source.
我知道这是由于numberOfRowsInSection的错误返回值造成的,因为当单元格animation还在播放的时候,开关回到原来的位置。 我试过禁用切换和挂钩其他事件处理程序下的代码,但似乎没有防止崩溃。 使用reloadData而不是animation也解决了问题,但我更喜欢漂亮的animation。
有没有人知道一个正确的方法来实现呢?
另一个(更优雅的)解决scheme是这样的:
我用这种方法修改了Alan MacGregor - (IBAction)SwitchDidChange:(id)sender
方法:
- (IBAction)SwitchDidChange:(UISwitch *)source { if (_showRows != source.on) { NSArray *aryTemp = [[NSArray alloc] initWithObjects: [NSIndexPath indexPathForRow:1 inSection:0], [NSIndexPath indexPathForRow:2 inSection:0], [NSIndexPath indexPathForRow:3 inSection:0], [NSIndexPath indexPathForRow:4 inSection:0],nil]; [_tblView beginUpdates]; _showRows = source.on; if (_showRows) { [_tblView insertSections:aryTemp withRowAnimation:UITableViewRowAnimationFade]; } else { [_tblView deleteSections:aryTemp withRowAnimation:UITableViewRowAnimationFade]; } [_tblView endUpdates]; } }
其他部分保持不变。
只需将开关的enabled
属性设置为NO
直到更新完成。
我有我的这个问题,避免崩溃的方式是不明确使用uiswitch,而是将信息中继到布尔值,inheritance人如何做到这一点。
将布尔值添加到实现文件的顶部
bool _showRows = NO;
更新你的uiswitch代码
- (IBAction)SwitchDidChange:(id)sender { NSArray *aryTemp = [[NSArray alloc] initWithObjects:[NSIndexPath indexPathForRow:1 inSection:0], [NSIndexPath indexPathForRow:2 inSection:0], [NSIndexPath indexPathForRow:3 inSection:0], [NSIndexPath indexPathForRow:4 inSection:0],nil]; if (_showRows) { _showRows = NO; _switch.on = NO; [_tblView deleteRowsAtIndexPaths:aryTemp withRowAnimation:UITableViewRowAnimationTop]; } else { _showRows = YES; _switch.on = YES; [_tblView insertRowsAtIndexPaths:aryTemp withRowAnimation:UITableViewRowAnimationBottom]; } }
最后更新你的numberOfRowsInSection
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == 0) { if (_showRows) { return 5; } else { return 1; } } return 0; }
UIControlEventValueChanged事件即使在控件的值没有真正改变时也会发生。 所以togglePush即使在交换机的值没有改变时也会被调用。 当您快速切换开关时,您可能不会总是从开>关>开>关等,可以关>开>开>关。
所以发生了什么事情是你连续得到两个连续的两个insertSections。 这显然是不好的。
为了解决这个问题,你需要记住button以前的状态(可能是一个ivar),如果新值(source.on)与以前的值不同,只执行插入(或删除)。
- parsingXamarin iOS的API崩溃报告
- 如何解释一个没有引用特定类的crashlog
- 请求用户在iPhone上崩溃后发送崩溃日志
- 未知的exception和崩溃
- iOS崩溃:由于未捕获的exception原因终止应用程序:UIPopoverPresentationController应该有一个非零的sourceView
- _GSRegisterPurpleNamedPortInPrivateNamespace – app store崩溃(附代码)
- 只有在iPad上按Share(分享)button后,iOS游戏才会崩溃
- Swift SourceKitService崩溃
- com.apple.NSURLSession-work EXC_BAD_ACCESS崩溃debugging