旋转设备时表格视图更新无效

Posted

技术标签:

【中文标题】旋转设备时表格视图更新无效【英文标题】:Invalid tableview update when rotating device 【发布时间】:2013-07-28 22:08:27 【问题描述】:

我正在使用我认为向表格视图添加项目的常见模式 -

主控制器创建模态控制器并将自己注册为委托 模态视图控制器出现 用户提供一些数据并点击模态导航栏中的保存按钮 模态视图控制器向其委托发送包含输入详细信息的消息 原控制器收到消息并关闭模态 原始控制器更新数据模型并在其 tableview 中插入新行

除了在一种特定情况下,这一切都很好。

如果在显示模式时设备旋转,则应用程序会在关闭模式后崩溃。新行已正确插入,但随后立即失败:

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], 

/SourceCache/UIKit_Sim/UIKit-2380.17/UITableView.m:1070
2013-07-28 17:28:36.404 NoHitterAlerts[36541:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (8) must be equal to the number of rows contained in that section before the update (8), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

我一生都无法弄清楚为什么会发生这种情况。如果我使用呈现的模态进行旋转,则始终有效的测试用例会失败。我注意到只需重新加载 tableview 而不是插入带有动画的行就可以了。

这是一个展示相同问题的简单项目: demo project

    在 iPhone sim 中运行项目 向列表中添加一个项目 - 工作正常 返回第一个屏幕,旋转到横向 再次运行相同的测试。仍然有效。 返回第一个屏幕,启动模式。 在模态仍然存在时旋转模拟器。点击“添加项目”。崩溃。

对这里可能发生的事情有什么想法吗?

【问题讨论】:

您使用什么代码将值添加到 tableView? 我添加了一个缩小的演示项目,其中只有几行代码,显示相同的问题。 【参考方案1】:

我明白你的问题是什么。在您的 MainController 的 -modalController:didAddItem: 方法中,您首先将对象添加到 self.arrayOfStrings,并且在 -dismissViewControllerAnimated 方法完成之前不将行插入到 tableView 中。

当 modalViewController 打开时方向未更改时,这似乎有效,但是如果您确实更改了方向,则 mainController 的方向在关闭之前不会更改。一旦发生这种情况,tableView 的数据似乎由于框架被更改而自动重新加载。

因此,由于 arrayOfStrings 在动画开始之前添加了对象,并且直到动画完成后才调用-insertRowsAtIndexPaths:withRowAnimation:,所以表格视图认为在到达插入方法时它已经获取了行.

为了解决这个问题,您只需在调用 tableView 上的 insertRows 方法之前,将用于将字符串添加到数组的方法移动到完成块中。

所以你的方法最终看起来像下面这样,你需要为你的实际项目做任何改变:

- (void)modalController:(ModalController *)controller didAddItem:(NSString *)string


    //dismiss the modal and add a row at the correct location
    [self dismissViewControllerAnimated:YES completion:^
        [self.arrayOfStrings addObject:string];     
        [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.arrayOfStrings.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];

    ]; 

【讨论】:

这很有意义 - 我怀疑这是轮换强制进行的某种重新加载。我想一个好的经验法则是让数据源和表视图的更新尽可能靠近。谢谢。

以上是关于旋转设备时表格视图更新无效的主要内容,如果未能解决你的问题,请参考以下文章

在大小更改时使集合视图布局无效的正确方法

加载 tableview 时应用程序崩溃并显示错误“无效更新:无效的节数”。

无效更新:iOS 中第 0 部分的行数无效

iOS中视图变换旋转使图像渲染效果无效

iPad 启动图像在 sim 中有效,但在设备上无效

Cocoa Touch:每次点击标签栏的标签时,如何更新表格视图?