1

シナリオ: UINavigationViewController に UICollectionViewControllers が含まれています。各コレクション ビューは JSON API からデータを取得する必要がありますが、これには少し時間がかかる場合があります。次に、コレクション ビューの各セルが独自の要求をサーバーに送信し、サムネイル画像を取得します。(明確にするために、デバッグのために無効にしたサムネイル要求を含めずに、これをどのように行っているかを示すシーケンス図を作成しました)。

コードは次のようになります。

-(void)buildDisplayItems
{
    NSLog(@"Collection VC (object: %@) with collection (object: %@) building display items on thread %@ (main thread: %c)", self, self.showingCollection, [NSThread currentThread], [NSThread isMainThread]);
    [self.showingCollection buildDisplayItemsWithPhotoBatch:self.nextBatch++]; // <-- this waits for the server request to be made, come back and get processed into arrays before returning.
    self.photos = self.showingCollection.photos;
    self.collections = self.showingCollection.subcategories;
    // Past this point, I cannot think of how these arrays would possibly get changed to trigger the 'mutated while being enumerated' errors.
    [self.collectionView reloadData];
}

問題は、ユーザーが適切なタイミングでナビゲーション ビューに戻ると、次のいずれかのエラーが発生することです。

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <NSConcreteMapTable: 0x1f047c80> was mutated while being enumerated.'

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSSetM: 0x203f26b0> was mutated while being enumerated.'

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[3]'

これらのエラーを発生させるには、アイテムを 3 ~ 4 回選択して、そのコレクション ビューがナビゲーション スタックにプッシュされ、すぐに [戻る] ボタンを押す必要があります。明らかに、最初の 2 つのエラーに対する私の第一印象は、データ ソースの配列が何らかの形で変更されているということでしたが、私が書いたものはそんなことをしているわけではありません。次に、cellForItemAtIndexPathが返された後に各セルのサムネイル画像が読み込まれることが問題であると考えたので、それを無効にしましたが、何も変わりませんでした。

いくつかの NSLog を散らしてみたところ、コレクション ビューがそのデリゲート メソッドを呼び出している間にこれが発生していることがわかりました。私は以下を追加することを確認しました:

-(void)viewWillDisappear:(BOOL)animated
{
    if (self.showingCollection != nil) {
        [self.showingCollection cancelOperations]; //for network requests
        NSLog(@"Collection VC (object: %@) will disappear", self);
    }
}

-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    self.collectionView.delegate = nil;
    self.collectionView.dataSource = nil;
    self.collectionView = nil;
}

しかし、これはエラーを止めるのに役立っていません。実際、クラッシュが発生したときに、「コレクション VC が消えます」というログ メッセージが表示されないことがあります。

もう 1 つの問題は、これらのエラーが発生し、デバッガーが UIApplicationMain 行のメイン関数で停止することです (これは、「すべての例外でブレーク」ブレークポイントで発生します)。そのため、エラーがどのようにトリガーされるかを特定する方法がありません。ゾンビを有効にしましたが、ゾンビからのログ メッセージがありません。(編集:「エラー: アドレスには、オブジェクト ファイル内のセクションを指すセクションが含まれていません」と言って、実際には空のスレッドで停止することがあります)

これらのコレクション ビューを設定して、戻るボタンをすばやく押しても世界が終わらないようにするにはどうすればよいですか?

編集 列挙中に変更されているコレクションを見つけるにはどうすればよいですか?

更新 スタックトレースを取得できないことについて話しているこのSOスレッドを見つけました。上記の例外のいずれかを取得するたびに、次のようなスタック トレースが表示されます。

*** First throw call stack:
(0x327453e7 0x3a440963 0x32744ec1 0x330f72c7 0x330f769b 0x330f825b 0x330fa0c7 0x330faefd 0x33103cab 0x3498c519 0x3498d5f1 0x3498d915 0x349920d9 0x34991fe3 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x330fa997 0x3498bf3d 0x345c73dd 0x34303513 0x343030b5 0x34303fd9 0x343039c3 0x343037d5 0x3434a567 0x3a87febb 0x3a87fb93 0x3a898fb8 0x32fe5fc7 0x3305d24f 0x3a88d0e1 0x3a88cfa8)
libc++abi.dylib: terminate called throwing an exception

そのスレッドの提案に従って、私は独自のキャッチされていない例外ハンドラーを実装し、次のスタック トレースを出力します。

    0   CoreFoundation                      0x327453ff <redacted> + 186
1   libobjc.A.dylib                     0x3a440963 objc_exception_throw + 30
2   CoreFoundation                      0x32744ec1 <redacted> + 0
3   Foundation                          0x330f72c7 <redacted> + 422
4   Foundation                          0x330f769b <redacted> + 298
5   Foundation                          0x330f825b <redacted> + 202
6   Foundation                          0x330fa0c7 <redacted> + 242
7   Foundation                          0x330faefd <redacted> + 500
8   Foundation                          0x33103cab <redacted> + 390
9   UIKit                               0x3498c519 <redacted> + 128
10  UIKit                               0x3498d5f1 <redacted> + 196
11  UIKit                               0x3498d915 <redacted> + 88
12  UIKit                               0x349920d9 <redacted> + 84
13  UIKit                               0x34991fe3 <redacted> + 182
14  CoreFoundation                      0x3268bacd CFArrayApplyFunction + 176
15  UIKit                               0x34991f97 <redacted> + 106
16  CoreFoundation                      0x3268bacd CFArrayApplyFunction + 176
17  UIKit                               0x34991f97 <redacted> + 106
18  CoreFoundation                      0x3268bacd CFArrayApplyFunction + 176
19  UIKit                               0x34991f97 <redacted> + 106
20  CoreFoundation                      0x3268bacd CFArrayApplyFunction + 176
21  UIKit                               0x34991f97 <redacted> + 106
22  CoreFoundation                      0x3268bacd CFArrayApplyFunction + 176
23  UIKit                               0x34991f97 <redacted> + 106
24  CoreFoundation                      0x3268bacd CFArrayApplyFunction + 176
25  UIKit                               0x34991f97 <redacted> + 106
26  Foundation                          0x330fa997 <redacted> + 166
27  UIKit                               0x3498bf3d <redacted> + 124
28  UIKit                               0x345c73dd <redacted> + 72
29  QuartzCore                          0x34303513 <redacted> + 214
30  QuartzCore                          0x343030b5 <redacted> + 460
31  QuartzCore                          0x34303fd9 <redacted> + 16
32  QuartzCore                          0x343039c3 <redacted> + 238
33  QuartzCore                          0x343037d5 <redacted> + 316
34  QuartzCore                          0x3434a567 <redacted> + 170
35  libsystem_c.dylib                   0x3a87febb _pthread_tsd_cleanup + 174
36  libsystem_c.dylib                   0x3a87fb93 <redacted> + 118
37  libsystem_c.dylib                   0x3a898fb8 pthread_exit + 27
38  Foundation                          0x32fe5fc7 <redacted> + 10
39  Foundation                          0x3305d24f <redacted> + 1002
40  libsystem_c.dylib                   0x3a88d0e1 <redacted> + 308
41  libsystem_c.dylib                   0x3a88cfa8 thread_start + 8
4

1 に答える 1