更新更改部分的单元格时,UITableView崩溃 [英] UITableView crash when updating cells that change sections

查看:102
本文介绍了更新更改部分的单元格时,UITableView崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个表,该表显示单个数组中的数据,并根据一组过滤器将项目组织到单独的部分中.每个过滤器都有一个对应的部分.我的用户界面允许用户点击每个表格单元格中嵌入的复选框.此复选框设置一个已选中"标志,该标志会影响该项目被过滤到的部分.这是一个示例:

I have a table that displays data from a single array and organizes the items into separate sections based on a set of filters. Each filter has a corresponding section. My UI allows the user to tap a check box embedded in each table cell. This check box sets a "checked" flag which affects which section the item is filtered to. Here's an example:

  • 第1节
    • 项目A
    • 项目B
    • Section 1
      • Item A
      • Item B

      点击项目A旁边的复选框应导致表格重新排列,如下所示:

      Tapping the check box next to Item A should cause the table to rearrange to look like this:

      • 第1节
        • 项目B
        • Section 1
          • Item B
          • 项目A

          以下是我用于响应复选框点击的代码.它找出该复选框属于哪一行,然后尝试创建一个动画块,该动画块从其旧部分删除该行,并在完成"部分的末尾添加一行.请记住,数组实际上并没有改变-数据过滤到节中的方式会根据项目的选中属性的值而改变.

          Below is my code for responding to the check box tap. It figures out which row the check box belongs to and then attempts to create an animation block that deletes the row from its old section and adds a row to the end of the "Done" section. Please keep in mind that the array doesn't actually change -- the way the data is filtered into the sections changes based on the value of the items' checked properties.

          - (IBAction)checkBoxTapped:(id)sender
          {
           // Get the table cell
           CheckBoxControl* checkBox = (CheckBoxControl*)sender;
          
           UITableViewCell* cell = (UITableViewCell*)[[sender superview] superview];
           UITableView* table = (UITableView*)[cell superview];
           NSIndexPath* indexPath = [table indexPathForCell:cell];
          
           Item* item = [self itemAtRow:[indexPath row] inSection:[indexPath section]];
           item.checked = checkBox.checked;
          
           Filter* filter = [filters objectAtIndex:DONE_INDEX];
           // We want the new row at the bottom of the "Done" section.
           NSIndexPath* newIndexPath = [NSIndexPath indexPathForRow:[self countItemsWithFilter:filter] inSection:DONE_INDEX];
          
           [table beginUpdates];
           [table insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
           [table deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
           [table endUpdates];
          }
          

          此代码始终会引发异常:

          This code always throws an exception:

          2010-01-13 00:19:44.802 MyApp[19923:207] *** Terminating app due to uncaught
          exception 'NSRangeException', reason:
          '*** -[NSMutableIndexSet addIndexesInRange:]:Range {2147483647, 1}
          exceeds maximum index value of NSNotFound - 1'
          

          谁能帮助我找出导致NSRangeException的原因?这是我的堆栈:

          Can anyone help me figure out what is causing the NSRangeException? Here's my stack:

          ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___
          obj_exception_throw
          +[NSException raise:format:arguments:]
          +[NSException raise:format:]
          -[NSMutableIndexSet addIndexesInRange:]
          -[NSMutableIndexSet addIndex:]
          -[_UITableViewUpdateSupport(Private) _computeRowUpdates]
          -[_UITableViewUpdateSupport initWithTableView:updateItems:oldRowData:oldRowRange:newRowRange:context:]
          -[UITableView(_UITableViewPrivate) _updateWithItems:withOldRowData:oldRowRange:newRowRange:context:]
          -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:]
          -[UITableView endUpdates]
          -[RootViewController checkBoxTapped:]
          

          如果此代码是完全错误的,那么我应该如何动画处理从一个部分中删除一行并将其添加到另一部分中?

          If this code is just plain wrong then how should I animate removing a row from one section and adding it to another?

          在此先感谢您能给我的帮助.

          Thanks in advance for any help you can give me.

          -迈克-

          推荐答案

          好的,我想我找到了一个更好的方法.我没有尝试使用过滤功能填充这些部分,而是决定为每个部分创建一个数组.每个部分的数组都包含数据源数组的索引.看起来像这样:

          Ok, I think I figured out a better approach. Instead of trying to populate the sections using a filtering function I decided to create an array for each section. Each section's array contains indexes into the data source array. It looks something like this:

          NSArray* data = [[NSArray alloc] initWithObjects:@"Apple", @"Banana", @"Cat", @"Dog", nil]];
          NSMutableArray* doneFilter = [[NSMutableArray alloc] init];
          NSMutableArray* othersFilter = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0],
                                          [NSNumber numberWithInt:1], [NSNumber numberWithInt:2],
                                          [NSNumber numberWithInt:3], nil];
          

          现在,当用户点击复选框时,我从othersFilter中删除了该项目的索引,并将其添加到doneFilter的底部.然后,我在表视图中删除并添加相应的行.这似乎比我以前拥有的稳定得多(没有引发异常!),并且具有允许过滤器自己排序的附加好处.

          Now, when the user taps the checkbox I remove the item's index from the othersFilter and add it to the bottom of the doneFilter. I then remove and add the corresponding rows in the table view. This seems much more stable than what I had before (no exceptions thrown!!) and has the added benefit of allowing the filters to have ordering of their own.

          这篇关于更新更改部分的单元格时,UITableView崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆