1

私は最近、私のマルチスレッド アプローチが原因で発生していることを知っていた厄介なバグを追跡してきました (最後にクラッシュレポートを追加します)。

私のアプリでは、UITableView を読み込み、Coredata を使用して保存したデータを入力します。このデータは Web サービスから取得するため、接続によっては時間がかかる場合があります。

とにかく、私はそれを少し追跡することができました.配列が空であってはいけないと思っていたのに、問題が空であることを知っています. その後、いつ

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

}

4

2 に答える 2

1

ここで説明したことから、ダウンロードを実行するプロセス、またはより正確にはイベント コールバックが、リロード データを呼び出す唯一の場所である必要があります。テーブル dataSet に新しいデータを追加した後に呼び出します。

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];
}
于 2011-01-19T22:40:21.233 に答える
0

できることの 1 つは、可変配列へのアクセスを @synchronized ブロックにカプセル化することです。このようにして、途中でデータ構造にアクセスしていないことを確認できます。そして、ルークが今言ったことにも同意します。

于 2011-01-19T22:41:26.320 に答える