2016-04-07 11 views
1

再生不能なクラッシュが発生していますが、その理由がわかりません。私は背景のキューに画像をキャッシュしています。イメージ名は、Core Data NSManagedObjectサブクラスCCCardのプロパティです。同時に、これらのCCCカードにもアクセスしているコレクションビューがあります。iOSコアデータdispatch_asyncバックグラウンドキューイングクラッシュ

以下は、関連するコードと注意事項です。

//CCDeckViewController.m -------------------------------------- 

- (void)viewDidLoad { 
    // This will fetch the CCCard objects from Core Data. 
    self.cards = [[CCDataManager shared] cards]; 

    [self cacheImages]; 
} 

- (void)cacheCardImages { 
    // Because these are NSManagedObjects, I access them in the background 
    // via their object ID. So pull the IDs out here. 
    NSArray *cardIds = [self.cards valueForKey:@"objectID"]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
     for (NSManagedObjectID *cardId in cardIds) { 

      // Fetch the actual CCCard object. 
      CCCard *card = (CCCard *)[[CCDataManager shared] objectWithId:cardId]; 

      // Cache the card's image if it's not already there. 
      NSString *key = [card thumbnailCacheKey]; 
      if ([self.cardImageCache objectForKey:key]) { 
       continue; 
      } 
      CCDiscardableImage *discardable = [CCHelper decompressedImageForPath:key size:[card thumbnailSize] tintable:[card tintable]]; 
      [self.cardImageCache setObject:discardable forKey:key]; 
     } 
    }); 
} 

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
    CCCard *card = self.cards[indexPath.item]; 

    // This line calls the code that crashes. 
    UIColor *color = [card color]; 

    // More code that returns the cell. 
} 


// CCCard.m -------------------------------------- 

- (UIColor *)color { 
    // Crash happens on this line. 
    if (self.colorId.integerValue == 0) { 
     // some code 
    } 
} 

はここで最も関連性の高いと思うCrashlyticsレポートからスタックトレースの一部である:

Thread #0: Crashed: com.apple.main-thread 
EXC_BREAKPOINT 0x000000000000defe 
0 CoreData      0x24c1b070 _sharedIMPL_pvfk_core + 247 
1 CoreData      0x24c1b071 _sharedIMPL_pvfk_core + 248 
2 myapp       0x4286f -[CCCard color] (CCCard.m:37) 
3 myapp       0x40bbb -[CCDeckViewController collectionView:cellForItemAtIndexPath:] (CCDeckViewController.m:127) 

Thread #4: com.apple.root.utility-qos 
0 libsystem_pthread.dylib  0x2321920c RWLOCK_GETSEQ_ADDR 
1 libsystem_pthread.dylib  0x23219295 pthread_rwlock_unlock + 60 
2 libobjc.A.dylib    0x22cb8e01 rwlock_tt<false>::unlockRead() + 8 
3 libobjc.A.dylib    0x22cb5af5 lookUpImpOrForward + 488 
4 libobjc.A.dylib    0x22cb5903 _class_lookupMethodAndLoadCache3 + 34 
5 libobjc.A.dylib    0x22cbbd7b _objc_msgSend_uncached + 26 
6 CoreData      0x24c1d3ab _PFObjectIDFastEquals64 + 38 
7 CoreFoundation     0x233eeed4 CFBasicHashFindBucket + 1820 
8 CoreFoundation     0x233ee775 CFDictionaryGetValue + 116 
9 CoreData      0x24c17037 _PFCMT_GetValue + 122 
10 CoreData      0x24c16ec7 -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:optionalHandler:withInlineStorage:] + 58 
11 CoreData      0x24c1b45d _PF_FulfillDeferredFault + 940 
12 CoreData      0x24c1afcf _sharedIMPL_pvfk_core + 86 
13 myapp       0x42991 -[CCCard imagePath] (CCCard.m:53) 
14 myapp       0x41d5b __39-[CCDeckViewController cacheCardImages]_block_invoke (CCDeckViewController.m:295) 

それは、開発中に発生したことがないので、任意の理論をテストすることはできませんので、それはイライラ。私は今問題を理解するためにコードとクラッシュレポートを理解しようとしています。私の推測では、CCCardオブジェクトのインスタンスメソッドにアクセスするので、フォールティングと何か関係がありますが、そのプロパティを読み取ろうとするとクラッシュします。しかし、なぜ?

+1

colorIdプロパティの種類は何ですか?モデルの型は何ですか? – dudeman

+0

'colorId'は' NSNumber'型です( 'NSManagedObject'以降でなければなりません)。 – guptron

答えて

4

スレッドの閉じ込めに違反しています。

コアデータのドキュメントでは、NSManagedObjectContextとそれに関連付けられたNSManagedObjectは、割り当てられたキューでのみアクセスする必要があります。

dispatch_asyncは、このルールに違反しており、修正する必要があります。あなたはコアデータをdispatch_asyncのように使用することはできません。

処理を非同期にする場合は、メインNSManagedObjectContextの子であるプライベートNSManagedObjectContextを生成してから、それに対して-performBlock:を実行する必要があります。そうすれば、適切に構成されたバックグラウンド処理が可能になります。

また、開発中にこのような問題が発生するので、-com.apple.CoreData.ConcurrencyDebug 1をオンにすることを強くお勧めします。

+0

答えMarcusに感謝します。実際にクラッシュの原因となっているスレッド閉じ込め違反であると判断する方法はありますか? 1つのデータストアに約5つのテーブルがあり、特定のテーブルの変更を1つ保存しようとすると常にクラッシュが発生します。私はアプリに並行性の違反がたくさんあることを知っていますが、私はこれらの違反が私に修正を求めてクラッシュを引き起こしていることを「証明」する方法がありません。あなたの考えを本当に感謝しますか?あなたの新しい本を楽しみにしています。 – shrutim

+1

最後の文で言ったように、通貨のデバッグフラグをオンにします: '-com.apple.CoreData.ConcurrencyDebug 1' 。 –

+0

ありがとう..私はそれをして、スレッドの問題があることを知っています。問題をスレッド化しているので、次のステートメントは正しいですか? "ManagedObjectContext.save()で発生したランダムクラッシュがスレッドの問題のために発生しました" – shrutim

関連する問題