2013-08-06 37 views
8

令人沮丧的事实:拨打tableView:moveRowAtIndexPath:toIndexPath:后,tableView:cellForRowAtIndexPath:未被调用。如何以编程方式重新加载移动的行?

呼叫reloadRowsAtIndexPaths:withRowAnimation:后或之前tableView:moveRowAtIndexPath:toIndexPath:UITableView更新模块也不起作用:它会引发不一致错误

我看到2个解决方法:删除+插入而不是移动或在另一个更新块中重新加载。

我的问题是:是否有一些其他方式来重新加载和移动UITableView的行内同一更新块?

回答

4

我不认为有可能在同一时间做一个移动和重新加载。我尝试了几种方法,我提出的最佳解决方案是在批量更新之前重新加载。我不动画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完全。您不会以这种方式获得内置的动画,但您可以制作自己的动画。

+0

这似乎是最好的方法。奇怪的是,从更新块中调用'reloadData'会取消动画。 – devios1

0

我已经成功了[TableView reloadData]。确保你正在更新你的数据源,并将重载代码放在合适的地方。

+2

'reloadData'没有任何关系。实际上,我的主要目标是摆脱'reloadData',因为它很丑陋(例如,闪烁)并中断用户。 – folex

0

当移动需要直接通过tableView.cellForRowAtIndexPath方法

获得细胞获得细胞后,细胞,只是手动更新。

0
[_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]; 
0

我在排序“dateModified”时遇到了类似的问题,但我也在该单元格的标签上显示该属性。 “移动”和“更新”都是必需的。 “移动”只被调用,所以正确的单元格被带到列表的顶部,但标签文本没有更新。

我对一个简单的UITableViewCell的解决方案。

首先,你打电话.move照常。直接调用自定义配置方法后 - 负责为单元格上的“更新”设置动画。这里

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 
    } 
} 

重用的配置方法,无需动画:

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) 
    } 
} 

的配置方法如下所示(注意动画是可选的)

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方法移至子类代码。重要的部分是有一个方法来更新单元格数据,可选动画。

相关问题