ios - 尝试移动 UITableView 行时崩溃

标签 ios iphone cocoa-touch uitableview

我有一些相当复杂的规则来移动 UITableView 中的行。每个部分的部分和行数未定义,并且根据各种规则,用户可以在部分内或部分之间将行移动到特定的其他位置。

所有数据都在更新,一切正常。但有时,移动一行后,应用程序会假发,突然出现一个应该显示一行的空白区域。

我正在使用:

              - (NSIndexPath *)tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath

指定允许用户根据单元格所在位置拖动行的位置。 98% 的时间都有效。但在某些情况下,当只允许用户在部分之间拖动时(不能对部分内的行重新排序)会出现此错误,然后应用程序会在滚动到没有行的区域后崩溃。

抛出的异常毫无用处:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (6) beyond bounds (6)

我的代码都不在堆栈上。最后一个 UITableView 特定的方法是

-[UITableView(UITableViewInternal) _visibleCellForGlobalRow:]

有人见过这个问题吗?有什么想法吗?

最佳答案

我只是遇到了我认为在我的应用程序中出现的相同问题。

情况是我有两个表格部分。可以在部分内和部分之间拖动项目。用户可以将单元格拖动到第一部分中的任何行,但在第二部分中,项目已排序,因此对于任何给定的单元格,只有一个有效行。

如果我 ScrollView 以便第 1 部分的底部和第 2 部分的顶部可见,请在第 1 部分中抓取一个排序到第 2 部分底部的项目,并将其拖到第 2 部分的顶部,我的 tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: 方法被调用,我返回正确的目标位置,即屏幕底部下方的几行。在 UI 中,您可以看到在屏幕底部创建了一个空单元格,这不是正确的目标行。

当您放开单元格时,在屏幕底部(第 2 部分中间)创建的虚假单元格会留在那里! tableView:cellForRowAtIndexPath: 甚至从未被调用过。一旦您尝试对该单元格执行任何操作,您就会崩溃。

我的第一个解决方案是在 tableView:moveRowAtIndexPath:toIndexPath: 的末尾调用 [tableView reloadData]。但这会导致崩溃,所以我在延迟后间接调用它。但是随后出现了另一个错误:在延迟的 reloadData 调用之后,tableView:moveRowAtIndexPath:toIndexPath: 再次被调用,并发出一个虚假请求,要求将项目移动到第一个项目的末尾部分到同一位置。因此,我不得不添加代码来忽略虚假的无操作请求。

所以,这是代码:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)pathSrc toIndexPath:(NSIndexPath *)pathDst
{
  // APPLE_BUG: after doing the delayed table reload (see below), we get a bogus
  // request to move a nonexistant cell to its current location
  if (pathSrc.row == pathDst.row && pathSrc.section == pathDst.section)
    return;

  // update your data model to reflect the move...

  // APPLE_BUG: if you move a cell to a row that's off-screen (because the destination
  // has been modified), the bogus cell gets created and eventually will cause a crash
  [self performSelector:@selector(delayedReloadData:) withObject:tableView afterDelay:0];
}

- (void)delayedReloadData:(UITableView *)tableView
{
  Assert(tableView == self.tableView);
  [tableView reloadData];
}

请注意,仍然存在一个 UI 错误。在屏幕上,被拖动的单元格被动画化到伪造的空单元格中。在动画结束时,用该行的正确数据重新绘制空单元格,但细心的用户会注意到被拖动的单元格被动画化到错误的位置,然后立即变形为另一个单元格。

这绝对是一个愚蠢的用户界面。我考虑过将正确的目标行滚动到屏幕上,但如果我这样做,它会用第二部分填满屏幕,然后任何试图拖回第一部分的尝试都会被我的(现在很烦人的)自动滚动不断地挫败。我可能必须更改 UI,但这需要对我的数据模型进行一些复杂而麻烦的更改。

关于ios - 尝试移动 UITableView 行时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1884491/

相关文章:

iphone - 如何知道 UITableView 以何种方式滚动

iphone - 资源后缀常量 : @2x, ~ipad, -568h

iphone - 多次点击时 UITextView textViewShouldBeginEditing 崩溃

objective-c - iOS 和 ARC : How to retain self during asynchronous operations?

iphone - 快速显示带有 Action 的图像?

ios - 具有核心数据的模型 Controller 抽象

iphone - 如何接收异步请求对单例的响应?

iphone - 对 NSUserDefaults 进行数学运算并重新保存 - 不起作用

ios - 如何检测用户何时通过 UIWebView 登录?

ios - 手腕掉落后用户通知未出现在 watch 上