【问题标题】:iOS 7 beginUpdates endUpdates inconsistentiOS 7 beginUpdates endUpdates 不一致
【发布时间】:2013-09-20 14:38:32
【问题描述】:

编辑: 此答案的解决方案与 iOS7 有时返回 NSIndexPath 和其他时间返回 NSMutableIndexPath 有关。该问题与begin/endUpdates 没有真正的关系,但希望该解决方案对其他人有所帮助。


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

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

- (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 方法的工作方式非常不一致。 didSelectRowAtIndexPath 方法在每次触摸时都会被正确调用(起初我以为 UI 被阻塞了),selectedIndexes 正在正确存储交替值。问题是,有时我触摸一个表格单元格并且所有方法都被正确调用,但单元格高度没有改变。有谁知道怎么回事?

【问题讨论】:

    标签: ios objective-c uitableview ios7 nsindexpath


    【解决方案1】:

    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 等。

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

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

    【讨论】:

    • 我通过创建“严格”indexPath 并在“forKey”查找中使用它来应用此解决方案。例如:NSIndexPath* strictIndexPath = [NSIndexPath indexPathForItem:indexPath.row inSection:indexPath.section];
    • @rob 我喜欢这样。用稍微修改的变体更新了我的答案。
    • 我遇到了同样的问题。但我不明白在原始海报代码中在哪里应用@TimothyMoose 的keyForIndexPath。我们应该在哪里调用这个方法?
    • @Brett 原始发布者在任何时候读取或写入selectedIndexes 字典时都会调用该方法。例如,他会使用selectedIndexes[[self keyForIndexPath indexPath]]而不是selectedIndexes[indexPath]
    • @MrAppleBR 我已经广泛测试了这个修复代码,所以我认为你还有其他问题。但是您可以尝试完全删除if 语句吗?如果它仍然不起作用,您可能需要发布一个新问题并包含您的视图控制器代码。
    【解决方案2】:

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

    【讨论】:

    • 他正在做的是一个众所周知的技巧,用于在 iOS 的早期版本中为单元格的行高设置动画。
    • @TimothyMoose 你的假设是正确的。你知道为什么它在 iOS7 中不起作用或者你知道解决方法吗?
    猜你喜欢
    • 2011-12-31
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多