iPhone UITable reloadRowsAtIndexPaths非常奇怪的问题

5

我正在尝试使用传入的图像更新单元格。 我有一个协议,当图像下载完成时调用相应的方法。 UITable的源是对象“Meeting”的NSArray。 每个Meeting都持有其表格单元格的indexPath,我在其中获取 -

(UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    Meeting * meeting = [tableDataSource objectAtIndex:indexPath.row];
... cell's init code
    meeting.cellPath = indexPath; // also tried [indexPath copy];
...
}

问题是,当我尝试使用存储的IndexPath更新单元格时,我遇到了一个奇怪的错误,提示我有一个我没有的NSMutable数组:

2012-07-20 20:15:18.007 MyNewbieApp[5734:207] meeting.cellPath =  [row = 2,section = 0]
2012-07-20 20:15:18.705 MyNewbieApp[5734:207] meeting.cellPath =  [row = 4,section = 0]
2012-07-20 20:15:18.728 MyNewbieApp[5734:207] meeting.cellPath =  [row = 5,section = 0]
2012-07-20 20:15:18.730 MyNewbieApp[5734:207] downloadDidFinishDownloading <NSIndexPath 0x79456f0> 2 indexes [0, 5]
2012-07-20 20:15:18.732 MyNewbieApp[5734:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 3 beyond bounds [0 .. 2]'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x02c70b99 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x02a6540e objc_exception_throw + 47
    2   CoreFoundation                      0x02c66695 -[__NSArrayM objectAtIndex:] + 261
    3   UIKit                               0x00556327 -[_UITableViewUpdateSupport(Private) _setupAnimationsForExistingVisibleCells] + 264
    4   UIKit                               0x00555b9b -[_UITableViewUpdateSupport initWithTableView:updateItems:oldRowData:newRowData:oldRowRange:newRowRange:context:] + 436
    5   UIKit                               0x003ab5d6 -[UITableView(_UITableViewPrivate) _updateWithItems:withOldRowData:oldRowRange:newRowRange:context:] + 1323
    6   UIKit                               0x003a7f03 -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 9179
    7   UIKit                               0x003974d3 -[UITableView reloadRowsAtIndexPaths:withRowAnimation:] + 56
    8   MyNewbieApp                         0x00017354 -[MeetingsVC downloadDidFinishDownloading:] + 174
    9   MyNewbieApp                         0x000173a6 -[MeetingsVC download:didFailWithError:] + 43
    10  MyNewbieApp                         0x00010e5f -[Meeting image] + 317
    11  MyNewbieApp                         0x00016f49 -[MeetingsVC tableView:cellForRowAtIndexPath:] + 2141
    12  UIKit                               0x0039ed6f -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 619
    13  UIKit                               0x00394e02 -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] + 75
    14  UIKit                               0x003a9774 -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1561
    15  UIKit                               0x003a17ec -[UITableView layoutSubviews] + 242
    16  QuartzCore                          0x02619481 -[CALayer layoutSublayers] + 177
    17  QuartzCore                          0x026191b1 CALayerLayoutIfNeeded + 220
    18  QuartzCore                          0x026122e0 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 302
    19  QuartzCore                          0x02612040 _ZN2CA11Transaction6commitEv + 292
    20  QuartzCore                          0x02642ebb _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 99
    21  CoreFoundation                      0x02c51f4b __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
    22  CoreFoundation                      0x02be6b27 __CFRunLoopDoObservers + 295
    23  CoreFoundation                      0x02bafce7 __CFRunLoopRun + 1575
    24  CoreFoundation                      0x02baf350 CFRunLoopRunSpecific + 208
    25  CoreFoundation                      0x02baf271 CFRunLoopRunInMode + 97
    26  GraphicsServices                    0x0318000c GSEventRunModal + 217
    27  GraphicsServices                    0x031800d1 GSEventRun + 115
    28  UIKit                               0x0033baf2 UIApplicationMain + 1160
    29  MyNewbieApp                         0x00002034 main + 102
    30  MyNewbieApp                         0x00001fc5 start + 53
)
terminate called after throwing an instance of 'NSException'

所以它是索引数组越界异常。但我没有任何有3个元素的NSMutableArray。我所有的数组都要大得多。啊,异常是从这里出来的:

    - (void)downloadDidFinishDownloading:(Meeting *)meeting
    {
        NSLog(@"downloadDidFinishDownloading %@",meeting.cellPath);
        //NSLog(@"downloadDidFinishDownloading meeting.cellPath =  [row = %d,section = %d]",meeting.cellPath.row,meeting.cellPath.section);

        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:meeting.cellPath] withRowAnimation:UITableViewRowAnimationNone];
        meeting.delegate = nil;
    }

- (void)download:(Meeting *)meeting didFailWithError:(NSError *)error{
    [self downloadDidFinishDownloading:meeting];
}

这个回调方法会在每次会议图片下载完成后被调用。如果我注释掉reloadRowsAtIndexPaths这行代码,一切都正常。否则就会出错。这到底是什么原因呢?我花了很多时间但毫无结果...我真的不知道这是怎么回事...更奇怪的是,问题总是出现在第五个元素上:)当我向上滚动表格内容时。而第五个元素并没有什么特别之处,我已经尝试了另一个数据集,但问题仍然存在。

更新:只有当代码调用download:(Meeting*)meeting didFailWithError方法时才会发生错误/崩溃。但它仍然有相同的meeting参数,我发送给downloadDidFinishDownloading。我也尝试了以下方法:
    - (void)download:(Meeting *)meeting didFailWithError:(NSError *)error{
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:meeting.cellPath] withRowAnimation:UITableViewRowAnimationNone];
            meeting.delegate = nil;
}

现在应用程序只会在reloadRowsAtIndexPaths方法中崩溃。


为什么下载失败后要重新加载行?行中有什么发生了改变吗? - moxy
是的,它会停止并隐藏旋转器,并显示一个标签,上面写着“DL err”。 - Stan
3个回答

0
一个想法是,您可能需要更新数据源对象“tableDataSource”,特别是在部分中的行数。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

编辑:

进一步阅读您的问题,您是否可以复制并粘贴cellForRowAtIndexPath中的“可重用单元格”部分(实际上是整个方法),我猜问题就在那儿。


当出现错误时,它不会到达那里。它经过了双重检查。在reloadRowsAtIndexPaths之后,应用程序崩溃了。 - Stan
同时,我的数据源对象“tableDataSource”是NSArray类型的,在添加或删除任何元素方面都没有更新。 - Stan

0

我相信你的数据源出现了问题。 由于所有的代码都很难说出问题在哪里。不过我有一个提示,可能对你有用。 在Xcode的断点选项卡上,点击左下角的加号按钮,会弹出一个窗口,然后点击“完成”。

再次运行你的应用程序,现在当它崩溃时,它将指出代码中的位置...

我不知道你是否已经拥有它..但还是提一下吧!


我的数据源对象“tableDataSource”是NSArray类型的,无论如何都没有更新,也就是没有添加或删除任何元素。 - Stan
你不能更改一个NSArray的内容,将其改为NSMutableArray即可。然后你就可以开始了。 - NSPunk
之前已经尝试过了,但是没有效果。此外,我并不想改变数据集,只是想修改其中包含的对象的一些属性。 - Stan

-1

试试这个:

[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:meeting.cellPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接