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

发布于 2024-10-13 05:07:15 字数 4281 浏览 6 评论 0原文

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

在我的应用程序中,我加载 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;
}

}

I have been tracking a nasty bug recently of which I knew it was occurring due to my multithreaded approach (I add the crashreport at the end).

In my App I load a UITableView and fill it with data I store using Coredata. This data in turn I retrieve from a webservice, thus it might take some time, depending on my connection.

Anyway, I have managed to track it down a little and I know the issue is because an array is empty though I thought it shouldn't be. Then, when

numberOfRowsInSection:(NSInteger)section

is called the program crashes - but only sometimes!!!

I was wondering how to debug this properly and my approach was to call

reloadData

on the tableView after the view finishes loading. But appearantly

- (void)viewDidLoad 

but of course this didn't help. Is the correct way here to create another thread and have it check repeatadly whether the data is ready and prepared? Any suggestions/opinions?

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 looks like:

- (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;
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暮倦 2024-10-20 05:07:15

根据您在此处描述的内容,执行下载的进程(或更准确地说,事件回调)应该是调用重新加载数据的唯一位置。将新数据添加到表数据集后调用它。

在 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];
}

From what you describe here your process that performs the download, or more precisely an event callback should be the only place calling reload data. calling it after adding new data to the table dataSet.

returning a 0 in numberOfRowsInSection does not cause a crash but if you are trying to get a nested array when the count is 0, this will crash. Post your numberOfRowsInSection method for us to gawk at.

EDIT:

Sounds/Looks like background thread is mutating the array while its trying to do an object count.

user210504 is right in saying that synchronising the array is likely stop this.

Typically you would sync writes and therefore preventing numberOfRowsInSection from counting if your background thread is mutating it. eg:

-(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];
}
浅笑轻吟梦一曲 2024-10-20 05:07:15

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

One thing that you can do is to encapsulate accesses to the Mutable Array in @synchronized block. This way you will be sure that you are not accessing the datastructure half way through. And then I also agree with what Luke just mentioned.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文