旋转设备时无效的tableview更新

时间:2013-07-28 22:08:27

标签: ios cocoa-touch uiview uitableview

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

  • 主控制器创建模态控制器并将自身注册为委托
  • 提供了模态视图控制器
  • 用户在模态导航栏中提供了一些数据并点击了保存按钮
  • 模态视图控制器向其委托发送包含输入详细信息的消息
  • 原始控制器接收消息并解除模态
  • 原始控制器更新数据模型并在其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

  1. 在iPhone sim中运行项目
  2. 将项目添加到列表中 - 工作正常
  3. 返回第一个屏幕,旋转至横向
  4. 再次运行相同的测试。仍然有效。
  5. 返回第一个屏幕,启动模式。旋转模拟器,同时仍显示模态。点击“添加项目”。崩溃。
  6. 关于这里可能发生的事情的任何想法?

1 个答案:

答案 0 :(得分: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];

    }]; 
}