2016-04-07 7 views
1

Ich bekomme einen nicht reproduzierbaren Absturz und ich bin mir nicht sicher warum. Ich speichere Bilder in einer Hintergrundwarteschlange. Die Bildnamen sind Eigenschaften einer Core Data NSManagedObject-Unterklasse CCCard. Gleichzeitig habe ich eine Sammlungsansicht, die auch auf diese CCCards zugreift.iOS Core Data dispatch_async Hintergrund Warteschlange Absturz

Hier sind die relevanten Code und Hinweise zu folgen.

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

Hier sind Teile des Stack-Trace aus dem Crashlytics Bericht Ich denke, am wichtigsten sind:

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) 

Es ist frustrierend, weil es nie während der Entwicklung geschieht, so kann alle Theorien nicht testen. Ich versuche den Code und den Absturzbericht zu verstehen, um das Problem jetzt herauszufinden. Meine Vermutung ist, dass es etwas mit Fehlern zu tun hat, weil es auf die Instanzmethode des CCCard-Objekts zugreift, aber dann abstürzt, wenn es versucht, die Eigenschaft daraus zu lesen. Aber warum?

+1

Was ist der Typ der ColorId-Eigenschaft? Und was ist der Typ im Modell? – dudeman

+0

'colorId' ist' NSNumber' Typ (es muss seit seinem 'NSManagedObject' sein). – guptron

Antwort

4

Sie verletzen die Threadbeschränkung.

Gemäß der Core Data-Dokumentation muss ein NSManagedObjectContext und ein damit verbundener NSManagedObject nur in der Warteschlange, der er zugewiesen ist, aufgerufen werden.

Ihr dispatch_async verletzt diese Regel und muss korrigiert werden. Es gibt kein Design mehr, in dem Sie Core-Daten in einer dispatch_async so verwenden können.

Wenn Sie wollen, dass die Verarbeitung asynchron sein, dann sollten Sie ein privates NSManagedObjectContext laichen, dass ein Kind Ihres Hauptes NSManagedObjectContext ist und dann ein -performBlock: gegen sie auszuführen. Dadurch erhalten Sie eine Hintergrundverarbeitung, die ordnungsgemäß konfiguriert ist.

Auch ich empfehle dringend, -com.apple.CoreData.ConcurrencyDebug 1 einschalten, da dies während der Entwicklung solche Probleme auftreten wird.

+0

Danke für die Antwort Marcus. Gibt es eine Möglichkeit, festzustellen, dass es tatsächlich die Thread-Confinement-Verletzung ist, die den Absturz verursacht? Ich habe ungefähr 5 Tabellen in einem einzigen Datenspeicher und ein Absturz tritt immer dann auf, wenn wir versuchen, die Änderungen einer bestimmten Tabelle zu speichern. Ich weiß, dass es viele Nebenläufigkeitsverletzungen in meiner App gibt, aber ich kann nicht "beweisen", dass diese Verstöße den Absturz verursachen, damit ich nach einer Lösung suche. würdest du deine Gedanken wirklich schätzen? BTW, Ich freue mich auf Ihr neues Buch – shrutim

+1

Wie ich im letzten Satz sagte: Schalten Sie die Währung Debug-Flag: '-com.apple.CoreData.ConcurrencyDebug 1' und Sie werden für ** bestimmte ** wissen, wenn Sie Threading-Probleme haben . –

+0

Danke .. Ich habe das getan und ich weiß, dass ich Threading Probleme habe..Given, dass ich Threading Probleme habe, ist die folgende Aussage korrekt? "Die zufälligen Abstürze in ManagedObjectContext.save() sind aufgrund von Threading-Problemen" – shrutim

Verwandte Themen