iOS核心数据调度\u异步后台队列崩溃

iOS核心数据调度\u异步后台队列崩溃,ios,core-data,grand-central-dispatch,fault,nscache,Ios,Core Data,Grand Central Dispatch,Fault,Nscache,我遇到了无法复制的崩溃,我不知道为什么。我正在后台队列中缓存图像。映像名称是核心数据NSManagedObject子类CCCard上的属性。同时,我有一个集合视图,它也在访问这些CC卡 以下是要遵循的相关代码和注释 //CCDeckViewController.m -------------------------------------- - (void)viewDidLoad { // This will fetch the CCCard objects from Core Dat

我遇到了无法复制的崩溃,我不知道为什么。我正在后台队列中缓存图像。映像名称是核心数据NSManagedObject子类CCCard上的属性。同时,我有一个集合视图,它也在访问这些CC卡

以下是要遵循的相关代码和注释

//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)
Thread#0:crash:com.apple.main-Thread
EXC_断点0x000000000000defe
0 CoreData 0x24c1b070\u sharedIMPL\u pvfk\u core+247
1 CoreData 0x24c1b071\u sharedIMPL\u pvfk\u core+248
2 myapp 0x4286f-[CCCard颜色](CCCard.m:37)
3 myapp 0x40bbb-[CCDeckViewController集合视图:cellForItemAtIndexPath:](CCDeckViewController.m:127)
线程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 rBlock_tt::unlockRead()+8
3 libobjc.A.dylib 0x22cb5af5 lookupimportforward+488
4 libobjc.A.dylib 0x22cb5903_class_lookupmethod和loadcache3+34
5 libobjc.A.dylib 0x22cbbd7b_objc_msgSend_uncached+26
6芯数据0x24c1d3ab _PFOBJECTIVASTEQUALS64+38
7芯基础0x233eeed4 CFBasicHashFindBucket+1820
8 CoreFoundation 0x233ee775 CFDictionaryGetValue+116
9核心数据0x24c17037 _PFCMT_GetValue+122
10 CoreData 0x24c16ec7-[NSManagedObjectContext(\u NSInternalAdditions)\u保留ID为:optionalHandler:withInlineStorage:+58的对象
11芯数据0x24c1b45d_PF_已完成故障+940
12 CoreData 0x24c1afcf\u sharedIMPL\u pvfk\u core+86
13 myapp 0x42991-[CCCard imagePath](CCCard.m:53)
14 myapp 0x41d5b\uuu39-[CCDeckViewController缓存图像]\uBlock\uInvoke(CCDeckViewController.m:295)

这很令人沮丧,因为它在开发过程中从未发生过,所以无法测试任何理论。我正在努力理解代码和崩溃报告,以找出问题所在。我的猜测是它与错误有关,因为它访问CCCard对象的实例方法,但在尝试从中读取属性时崩溃。但是为什么呢

您违反了线程限制

根据核心数据文档,只能在分配给它的队列上访问
NSManagedObjectContext
及其关联的任何
NSManagedObject

您的
dispatch\u async
违反了该规则,需要更正。现在已经没有一种设计可以像这样在
dispatch\u async
中使用核心数据

如果希望处理是异步的,那么应该生成一个私有的
NSManagedObjectContext
,它是主
NSManagedObjectContext
的子对象,然后对其执行
-performBlock:
。这将为您提供正确配置的后台处理


另外,我强烈建议打开
-com.apple.CoreData.concurrenceydebug 1
,因为这样会在开发过程中发现类似问题。

您违反了线程限制

根据核心数据文档,只能在分配给它的队列上访问
NSManagedObjectContext
及其关联的任何
NSManagedObject

您的
dispatch\u async
违反了该规则,需要更正。现在已经没有一种设计可以像这样在
dispatch\u async
中使用核心数据

如果希望处理是异步的,那么应该生成一个私有的
NSManagedObjectContext
,它是主
NSManagedObjectContext
的子对象,然后对其执行
-performBlock:
。这将为您提供正确配置的后台处理


另外,我强烈建议打开
-com.apple.CoreData.concurrenceydebug 1
,因为这样会在开发过程中发现类似问题。

colorId属性的类型是什么?模型中的类型是什么?
colorId
NSNumber
类型(它必须是因为它的
NSManagedObject
)。colorId属性的类型是什么?模型中的类型是什么?
colorId
NSNumber
类型(必须是因为它的
NSManagedObject
),谢谢您的回答Marcus。是否有任何方法可以确定导致崩溃的确实是线程限制冲突?我在一个数据存储中有大约5个表,当我们试图保存一个特定表的更改时,总是会发生崩溃。我知道我的应用程序中有很多并发冲突,但我无法“证明”这些冲突导致了崩溃,让我推动修复。你真的很感激你的想法吗?顺便说一句,期待您的新书,正如我在最后一句中所说的:打开currency debug标志:
-com.apple.CoreData.concurrency debug 1
,您将确定是否存在线程问题。谢谢。。我这样做了,我知道我有线程问题..鉴于我有线程问题,下面的说法正确吗?“ManagedObjectContext.save()中发生的随机崩溃是由于线程问题造成的”不,这是不正确的。如果您得到的异常会触发保存中的断点,则这是合并冲突,而不是实际崩溃。继续吧。如果您遇到实际的崩溃,那么请阅读崩溃,它会告诉您是否是线程崩溃。谢谢您的回答Marcus。是否有任何方法可以确定导致崩溃的确实是线程限制冲突?我有一个