令人沮丧的事实:在调用tableView:moveRowAtIndexPath:toIndexPath:
后,tableView:cellForRowAtIndexPath:
不会被调用该行。
在reloadRowsAtIndexPaths:withRowAnimation:
tableView:moveRowAtIndexPath:toIndexPath:
内UITableView
之后或之前拨打{{1}}也不会有效:它会引发不一致错误。
我看到了2个解决方法:删除+插入而不是移动或在另一个更新块中重新加载。
我的问题是:还有其他方法可以在同一个更新块中重新加载和移动UITableView的行吗?
答案 0 :(得分:5)
我认为不可能同时进行移动和重新加载。我已经尝试了几种方法,我提出的最佳解决方案是在批量更新之前进行重新加载。我没有动画reloadRows
,因为它似乎与批量更新动画冲突。
[tableView reloadRowsAtIndexPaths:indexPathsToReload withRowAnimation:UITableViewRowAnimationNone];
[tableView beginUpdates];
//inserts, deletes and moves here
[tableView endUpdates];
另外,我通常将我的单元配置逻辑放在一个单独的方法中,如:
- (void)tableView:(UITableView *)tableView configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
这样我就可以直接调用它并完全绕过reloadRowsAtIndexPaths
。您也不会以这种方式获得内置动画,但您可以自己制作动画。
答案 1 :(得分:1)
[_tableview beginUpdates];
// write code here to delete and move row...
[_tableview endUpdates];
// now after end update call reload method to reload cell..
[self.tableview reloadRowsAtIndexPaths:[NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:_arrayForData.count-1 inSection:indexpathforSelectedRow.section], nil] withRowAnimation:UITableViewRowAnimationNone];
答案 2 :(得分:0)
我在[TableView reloadData]上取得了成功。确保您正在更新数据源,并将重新加载代码放在适当的位置。
答案 3 :(得分:0)
我在“dateModified”上排序时遇到了类似的问题,但我也在单元格的标签上显示了该属性。 “移动”和“更新”都是必需的。 “move”只被调用,因此正确的单元格被放到列表顶部,但标签文本没有更新。
我的简单UITableViewCell解决方案。
首先,你正常打电话.move。在您调用自定义配置方法之后直接调用 - 该方法负责为单元格上的“更新”设置动画。
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
tableView.insertRows(at: [newIndexPath!], with: .fade)
case .delete:
tableView.deleteRows(at: [indexPath!], with: .fade)
case .update:
tableView.reloadRows(at: [indexPath!], with: .fade)
case .move:
tableView.moveRow(at: indexPath!, to: newIndexPath!)
// Can't "reload" and "move" to same cell simultaneously.
// This is an issue because I'm sorting on date modified and also displaying it within a
// label in the UITableViewCell.
// To have it look perfect you have to manually crossfade the label text, while the UITableView
// does the "move" animation.
let cell = tableView.cellForRow(at: indexPath!)!
let note = fetchedResultsController.object(at: newIndexPath!)
configure(cell: cell, note: note, animated: true)
}
}
configure方法如下所示(注意动画是可选的):
internal func configure(cell: UITableViewCell, note: Note, animated: Bool = false) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .medium
let dateString = dateFormatter.string(from: note.dateModified as Date)
if animated {
UIView.transition(with: cell.contentView, duration: 0.3, options: .transitionCrossDissolve, animations: {
cell.textLabel?.text = dateString
}, completion: nil)
} else {
cell.textLabel?.text = dateString
}
}
在没有动画的情况下重复使用configure方法:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CellReuseIdentifier, for: indexPath)
let note = fetchedResultsController.object(at: indexPath)
configure(cell: cell, note: note)
return cell
}
如果你有一个更复杂的单元格(子类),你可以将configure方法移动到子类代码。重要的部分是有一个方法来更新动画可选的单元格数据。