libobjc.A.dylib objc_msg由于后台线程中的核心数据使用而发送崩溃 [英] libobjc.A.dylib objc_msgSend crash occurring with core data usage in background thread

查看:178
本文介绍了libobjc.A.dylib objc_msg由于后台线程中的核心数据使用而发送崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在调查在我的应用程序的Crashlytics控制台中报告的一次较为频繁的崩溃.

I'm looking into a somewhat frequent crash reported in my application's Crashlytics console.

我拥有的许多示例之一具有以下崩溃的线程堆栈跟踪信息:

One of the many examples I have has the following crashed thread stacktrace:

#11. Crashed: com.apple.root.default-qos
0  libobjc.A.dylib                0x22f3fa86 objc_msgSend + 5
1  Foundation                     0x23ee3005 -[NSString caseInsensitiveCompare:] + 28
2  Foundation                     0x23ed10bd _NSCompareObject + 28
3  Foundation                     0x23ed109d _NSSortFunctionOne + 120
4  CoreFoundation                 0x2373e6a3 __CFSimpleMergeSort + 114
5  CoreFoundation                 0x2373e6c5 __CFSimpleMergeSort + 148
6  CoreFoundation                 0x2373e6d9 __CFSimpleMergeSort + 168
7  CoreFoundation                 0x2373e6c5 __CFSimpleMergeSort + 148
8  CoreFoundation                 0x2373e6d9 __CFSimpleMergeSort + 168
9  CoreFoundation                 0x2368ac35 CFSortIndexes + 404
10 CoreFoundation                 0x2368c241 CFMergeSortArray + 176
11 Foundation                     0x23ed0a9d _sortedObjectsUsingDescriptors + 456
12 Foundation                     0x23f9c9fb -[NSSet(NSKeyValueSorting) sortedArrayUsingDescriptors:] + 510
13 MyApp                          0x6d431 __24-[MyApp refresh]_block_invoke (MyApp.m:247)
14 CoreFoundation                 0x23769499 __NSArrayEnumerate + 372
15 CoreFoundation                 0x236e6c3b -[NSArray enumerateObjectsWithOptions:usingBlock:] + 62
16 MyApp                          0x6d17d -[MyApp refresh] (MyApp.m:263)
17 MyApp                          0xa97eb __52-[MyAppRequest updateAfterNotification:]_block_invoke (MyAppRequest.m:1175)
18 libdispatch.dylib              0x23307cbf _dispatch_call_block_and_release + 10
19 libdispatch.dylib              0x233136a1 _dispatch_root_queue_drain + 1572
20 libdispatch.dylib              0x2331307b _dispatch_worker_thread3 + 94
21 libsystem_pthread.dylib        0x234a6e0d _pthread_wqthread + 1024
22 libsystem_pthread.dylib        0x234a69fc start_wqthread + 8

崩溃的其他实例发生在同一应用程序代码中(在 MyApp 类的 refresh 方法中),但是发生在 CoreFoundation sortedArrayUsingDescriptors 方法逻辑.例如,另一个崩溃示例stacktrace具有:

Other instances of the crash occur in the same app code (in the refresh method of MyApp class), but during different parts of the CoreFoundation sortedArrayUsingDescriptors method logic. For example, another crash example stacktrace has:

0  libobjc.A.dylib                0x1823cdb90 objc_msgSend + 16
1  CoreFoundation                 0x182c42738 CFStringCompareWithOptionsAndLocale + 232
2  Foundation                     0x183644840 _NSCompareObject + 64
3  CoreFoundation                 0x182d150f4 __CFSimpleMergeSort + 196
4  CoreFoundation                 0x182d15124 __CFSimpleMergeSort + 244
5  CoreFoundation                 0x182d15124 __CFSimpleMergeSort + 244
6  CoreFoundation                 0x182d15124 __CFSimpleMergeSort + 244
7  CoreFoundation                 0x182d1513c __CFSimpleMergeSort + 268
8  CoreFoundation                 0x182d15124 __CFSimpleMergeSort + 244
9  CoreFoundation                 0x182d15124 __CFSimpleMergeSort + 244
10 CoreFoundation                 0x182d15124 __CFSimpleMergeSort + 244
11 CoreFoundation                 0x182c3b738 CFSortIndexes + 472
12 CoreFoundation                 0x182c3cf58 CFMergeSortArray + 220
13 Foundation                     0x1836440f8 _sortedObjectsUsingDescriptors + 564
14 Foundation                     0x183725120 -[NSSet(NSKeyValueSorting) sortedArrayUsingDescriptors:] + 564
15 MyApp                          0x10006f264 __24-[MyApp refresh]_block_invoke (MyApp.m:247)

刷新的应用代码为:

- (void)refresh {
    NSArray *products = [self getProducts];
    NSMutableArray *validProducts = [NSMutableArray array];
    [products enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        Product *prod = obj;

        // Convert to internal native format (MyAppProduct) for business reasons...
        MyAppProduct *myAppProd = [[MyAppProduct alloc] init];
        myAppProd.ID = prod.id;
        myAppProd.name = prod.name;

        NSArray *subProds = [prod.subProds sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"subProds" ascending:NO]]];
        NSMutableArray *validSubProds = [NSMutableArray array];
        [subProds enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            SubProd *subProd = obj;

            // Convert to internal native format (MyAppSubProduct) for business reasons...
            MyAppSubProduct *myAppSubProd = [[MyAppSubProduct alloc] initWithSubProd:subProd];
            [validSubProds addObject:myAppSubProd];
        }];
        myAppProd.subProds = validSubProds;
        myAppProd.count = [product.count integerValue];

        // Add to array
        [validProducts addObject:myAppProd];
    }];

    // Apply array to self
    _products = validProducts
}

其中的getProducts是:

where getProducts is:

- (NSArray*)getProducts {
    NSFetchRequest *productFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Products"];

    // Filter
    NSMutableArray *productsPredicates = [NSMutableArray array];
    [productsPredicates addObject:[NSPredicate predicateWithFormat:@"life_uid == %@", req.lifeUid]];
    [productsPredicates addObject:[NSPredicate predicateWithFormat:@"hidden == %@", @NO]];
    [productFetchRequest setPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:productsPredicates]];

    // Sort
    NSSortDescriptor *sortProductsByName = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    [productFetchRequest setSortDescriptors:@[sortProductsByName]];

    [productFetchRequest setReturnsObjectsAsFaults:NO];
    [productFetchRequest setRelationshipKeyPathsForPrefetching:@[@"subprods", @"subprods.special"]];

    NSManagedObjectContext *moc = [MyAppCoreDataController sharedController].mainManagedObjectContext;
    NSError *error = nil;
    NSArray *products = [moc executeFetchRequest:productFetchRequest error:&error];
    if (error) {
        NSLog(@"Error fetching products %@", error);
    }
    return products;
}

刷新方式如下:

- (void)updateAfterNotification:(NSNotification *)notification {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [[MyApp instance] refresh];
    });
}

推荐答案

很可能是因为您没有正确处理Core Data并发.使用 NSPrivateQueueConcurrencyType NSMainQueueConcurrencyType 创建托管对象上下文时,您必须将所有核心数据访问权限放入对 performBlock 的调用中code>或 performBlockAndWait .其中包括获取以及访问所获取对象的属性值.

Most likely it's because you're not handling Core Data concurrency correctly. When you create a managed object context using NSPrivateQueueConcurrencyType or NSMainQueueConcurrencyType, you must put all Core Data access inside a call to performBlock or performBlockAndWait. That includes fetches as well as accessing attribute values of fetched objects.

您正在使用 dispatch_async ,这不是处理Core Data并发的正确方法.您应该切换为使用 performBlock performBlockAndWait .

You're using dispatch_async, which is not the right way to handle concurrency with Core Data. You should switch to using performBlock or performBlockAndWait.

这篇关于libobjc.A.dylib objc_msg由于后台线程中的核心数据使用而发送崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆