iOS 7 beginUpdates endUpdates不一致

编辑 :这个答案的解决scheme是有关iOS7有时返回NSIndexPath和其他时间返回NSMutableIndexPath 。 这个问题与begin/endUpdates没有什么关系,但希望解决scheme能够帮助其他人。


所有 – 我在iOS 7上运行我的应用程序,我遇到了UITableViewbeginUpdatesendUpdates方法的问题。

我有一个tableview需要改变一个单元格的高度时,触摸。 以下是我的代码:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // If our cell is selected, return double height if([self cellIsSelected:indexPath]) { return 117; } // Cell isn't selected so return single height return 58; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ ChecklistItemCell *cell = (ChecklistItemCell *)[self.tableview cellForRowAtIndexPath:indexPath]; [cell.decreaseButton setHidden:NO]; [cell.increaseButton setHidden:NO]; // Toggle 'selected' state BOOL isSelected = ![self cellIsSelected:indexPath]; DLog(@"%@", selectedIndexes); DLog(@"is selected: %@", isSelected ? @"yes":@"no"); // Store cell 'selected' state keyed on indexPath NSNumber *selectedIndex = @(isSelected); selectedIndexes[indexPath] = selectedIndex; [tableView beginUpdates]; [tableView endUpdates]; } 

beginUpdatesendUpdates方法工作相当不一致。 didSelectRowAtIndexPath方法会在每次触摸时被正确调用(我认为一开始UI被阻塞),而selectedIndexes正确地存储交替值。 问题是,有时我触摸一个表格单元格,所有的方法都调用正确,但单元格高度不会改变。 任何人都知道发生了什么事?

iOS7中的行为有所变化,其中索引path有时是NSIndexPath实例,其他时间是UIMutableIndexPath 。 问题是这两个类之间的isEqual总是返回NO 。 因此,您不能可靠地使用索引path作为字典键或依赖于isEqual其他情况。

我可以想到几个可行的解决scheme:

  1. 编写一个总是返回NSIndexPath实例并使用它来生成密钥的方法:

     - (NSIndexPath *)keyForIndexPath:(NSIndexPath *)indexPath { if ([indexPath class] == [NSIndexPath class]) { return indexPath; } return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]; } 
  2. 通过数据识别行,而不是索引path。 例如,如果您的数据模型是一个NSString数组,则使用该string作为您的selectedIndexes映射关键字。 如果你的数据模型是一个NSManagedObjects数组,使用objectID

我在我的代码中成功地使用了这两个解决scheme。

编辑修改解决scheme(1)基于@ robbuild议返回NSIndexPaths而不是NSStrings

beginUpdates之后不应该立即endUpdates 。 后者的文档指出,“开始一系列的方法调用,插入,删除或select接收器的行和部分。 这表明它应该在willSelectRowAtIndexPath: endUpdates willSelectRowAtIndexPath: endUpdates应该在didSelectRowAtIndexPath调用。