iOS 7 beginUpdates endUpdates不一致

时间:2013-09-20 14:38:32

标签: ios objective-c uitableview ios7 nsindexpath

修改: 此答案的解决方案与iOS7相关,有时会返回NSIndexPath,有时会返回NSMutableIndexPath。这个问题与begin/endUpdates没有关系,但希望解决方案能够帮助其他人。


全部 - 我在iOS 7上运行我的应用程序,而beginUpdates的{​​{1}}和endUpdates方法遇到了问题。

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

UITableView

- (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]; } beginUpdates方法工作非常不一致。每次触摸都会正确调用endUpdates方法(我认为UI首先被阻止),didSelectRowAtIndexPath正确存储交替值。问题是,有时我触摸表格单元格并且所有方法都被正确调用,但单元格高度不会改变。有谁知道发生了什么事?

2 个答案:

答案 0 :(得分:21)

iOS7中的行为发生了变化,其中索引路径有时是NSIndexPath的实例,有时是UIMutableIndexPath的实例。问题是这两个类之间的isEqual总是会返回NO。因此,您无法可靠地将索引路径用作字典键或在依赖isEqual的其他方案中使用。

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

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

    - (NSIndexPath *)keyForIndexPath:(NSIndexPath *)indexPath
    {
        if ([indexPath class] == [NSIndexPath class]) {
            return indexPath;
        }
        return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
    }
    
  2. 按数据识别行,而不是索引路径。例如,如果您的数据模型是NSString的数组,请将该字符串用作selectedIndexes地图的关键字。如果您的数据模型是NSManagedObjects的数组,请使用objectID

  3. 我在我的代码中成功使用了这两种解决方案。

    编辑修改后的解决方案(1)基于@ rob关于返回NSIndexPaths而不是NSStrings的建议。

答案 1 :(得分:0)

endUpdates之后不应立即调用{p> beginUpdates。后者的文档说明,“开始一系列方法调用,插入,删除或选择接收器的行和部分。”这表明它应该在willSelectRowAtIndexPath:中调用,而endUpdates应该在didSelectRowAtIndexPath中调用。