iPhone - Tableview 中的多线程 - 可行的方法?

Posted

技术标签:

【中文标题】iPhone - Tableview 中的多线程 - 可行的方法?【英文标题】:iPhone - Multithreading in Tableview - feasible approach? 【发布时间】:2011-01-19 21:31:54 【问题描述】:

我最近一直在跟踪一个令人讨厌的错误,我知道它是由于我的多线程方法而发生的(我在最后添加了崩溃报告)。

在我的应用程序中,我加载了一个 UITableView 并用我使用 Coredata 存储的数据填充它。我又从网络服务中检索这些数据,因此可能需要一些时间,具体取决于我的连接。

无论如何,我已经设法找到了一点,我知道问题是因为数组是空的,尽管我认为它不应该是空的。那么,当

numberOfRowsInSection:(NSInteger)section

被称为程序崩溃——但只是有时!!!

我想知道如何正确调试它,我的方法是调用

reloadData

视图加载完成后在 tableView 上。不过貌似

- (void)viewDidLoad 

但这当然没有帮助。这里是创建另一个线程并让它重复检查数据是否准备就绪的正确方法吗?有什么建议/意见吗?

2011-01-19 21:50:49.605 myApp[2017:307] *** Terminating app due to uncaught exception         
'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'
*** Call stack at first throw:
(
0   CoreFoundation                      0x314d0987 __exceptionPreprocess + 114
1   libobjc.A.dylib                     0x319a149d objc_exception_throw + 24
2   CoreFoundation                      0x31462795 -[__NSArrayM objectAtIndex:] + 184 
3   myApp                                 0x000092f7 -[MyTableViewController tableView:numberOfRowsInSection:] + 106
4   UIKit                               0x33902bcf -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 1338
5   UIKit                               0x33903529 -[UITableViewRowData(UITableViewRowDataPrivate) _ensureSectionOffsetIsValidForSection:] + 120
6   UIKit                               0x33902645 -[UITableViewRowData numberOfRows] + 96
7   UIKit                               0x3390207b -[UITableView noteNumberOfRowsChanged] + 82
8   UIKit                               0x33901bff -[UITableView reloadData] + 582
9   UIKit                               0x33904a0b -[UITableView _reloadDataIfNeeded] + 50
10  UIKit                               0x33904e63 -[UITableView layoutSubviews] + 18
11  UIKit                               0x338b10cf -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 26
12  CoreFoundation                      0x3146ebbf -[NSObject(NSObject) performSelector:withObject:] + 22
13  QuartzCore                          0x30a6c685 -[CALayer layoutSublayers] + 120
14  QuartzCore                          0x30a6c43d CALayerLayoutIfNeeded + 184
15  QuartzCore                          0x30a6656d _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 212
16  QuartzCore                          0x30a66383 _ZN2CA11Transaction6commitEv + 190
17  QuartzCore                          0x30a70e4f _ZN2CA11Transaction5flushEv + 46
18  QuartzCore                          0x30a6db75 +[CATransaction flush] + 24
19  UIKit                               0x338e803f -[UIApplication _reportAppLaunchFinished] + 30
20  UIKit                               0x338d6317 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 462
21  UIKit                               0x338a248b -[UIApplication handleEvent:withNewEvent:] + 1114
22  UIKit                               0x338a1ec9 -[UIApplication sendEvent:] + 44
23  UIKit                               0x338a1907 _UIApplicationHandleEvent + 5090
24  GraphicsServices                    0x35d66f03 PurpleEventCallback + 666
25  CoreFoundation                      0x314656ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
26  CoreFoundation                      0x314656c3 __CFRunLoopDoSource1 + 166
27  CoreFoundation                      0x31457f7d __CFRunLoopRun + 520
28  CoreFoundation                      0x31457c87 CFRunLoopRunSpecific + 230
29  CoreFoundation                      0x31457b8f CFRunLoopRunInMode + 58
30  UIKit                               0x338d5309 -[UIApplication _run] + 380
31  UIKit                               0x338d2e93 UIApplicationMain + 670
32  myApp                               0x000029bf main + 70
33  myApp                               0x00002974 start + 40
)
terminate called after throwing an instance of 'NSException'

numberOfRows 看起来像:

- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section 
// Return the number of rows in the section.
NSLog(@"number of rows in section");
if (section == mySection) 

    return  [[articleArrays objectAtIndex:section] count];  

 else 
    return 0;

【问题讨论】:

【参考方案1】:

根据您在此处的描述,您执行下载的过程,或者更准确地说,事件回调应该是唯一调用重新加载数据的地方。在向表数据集添加新数据后调用它。

在 numberOfRowsInSection 中返回 0 不会导致崩溃,但如果您在计数为 0 时尝试获取嵌套数组,则会崩溃。发布您的numberOfRowsInSection 方法让我们盯着看。

编辑:

听起来/看起来后台线程在尝试进行对象计数时正在改变数组。

user210504 说得对,同步阵列可能会停止。

通常你会同步写入,因此如果你的后台线程正在改变它,你会阻止 numberOfRowsInSection 计数。例如:

-(void)downloadFinished

NSMutableArray * array  = [[NSArray alloc] init];//t
id * obj;//obj is your row data object.

@synchronized(ar)

    [array addObject:obj];//ar is your dataSet


[array release];

【讨论】:

我补充说。有趣的是,如上所述,这是随机发生的,好像他有时设法做到这一点足够快。 好吧,我确实解决了这个问题,但不知何故有所不同。虽然我想知道,为什么 @synchronized(articleArrays) 对我不起作用。无论如何,我认为您的方法是正确的,所以感谢您这样指导我!【参考方案2】:

您可以做的一件事是将对可变数组的访问封装在@synchronized 块中。这样,您将确保您不会在中途访问数据结构。然后我也同意卢克刚才提到的。

【讨论】:

你能详细说明第一部分吗?

以上是关于iPhone - Tableview 中的多线程 - 可行的方法?的主要内容,如果未能解决你的问题,请参考以下文章

TableView Swift 中的多选

iphone中的tableView没有更新

iPhone 4.3 的 Tableview 中的多个单元格选择

iphone中的可扩展tableView

iphone中的可扩展tableView

iPhone中的自动tableView单元格大小?