ios - RKManagedObjectRequestOperation objc_msgSend 期间 RestKit 崩溃

标签 ios objective-c core-data restkit nsfetchrequest

我有一个函数,我们将其称为“更新函数”,它将 RKManagedObjectRequestOperation 发送到我的服务器以检索一些对象。我将此操作配置为自动保存到持久存储,然后启动它。在 RKManagedObjectRequestOperation 的“成功”完成处理程序中,我调用一个函数,该函数执行 NSFetchRequest 来获取满足特定条件的更新的对象列表,并在完成 block 中有新数据时传回该数组和 BOOL 标志。

在“更新函数”的完成处理程序中,我调用一个名为 getUpdatedList 的函数,该函数执行 NSFetchRequest 请求,如下所示:

    NSUInteger now = [[NSDate date] timeIntervalSince1970];

    NSArray *predicates = @[
                            [NSPredicate predicateWithFormat:@"endAt > %d", now],
                            [NSPredicate predicateWithFormat:@"deleted != %@", @YES]
                            ];

    NSManagedObjectContext *managedObjectContext = [self managedObjectContext]; //(REMOVED: _objectManager.managedObjectStore.persistentStoreManagedObjectContext;)

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
    [fetchRequest setPredicate:compoundPredicate];

    NSError *error = nil;

    NSArray *fetchedRecords = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

    if (sortDescriptor) {
        fetchedRecords = [fetchedRecords sortedArrayUsingDescriptors:@[sortDescriptor]];
    }

    DDLogInfo(@"Retrieving list of %@ objects from local database - got %d results.", entityName, fetchedRecords.count);

    return fetchedRecords;

- (NSManagedObjectContext *)managedObjectContext {
    if (_globalContext != nil) {
        return _globalContext;
    }

    NSPersistentStoreCoordinator *coordinator = _objectManager.managedObjectStore.persistentStoreCoordinator;
    if (coordinator != nil) {
        _globalContext = [[NSManagedObjectContext alloc] init];
        [_globalContext setPersistentStoreCoordinator:coordinator];
    }
    return _globalContext;
}

现在,我自己从未亲眼见过这种崩溃,所以我不知道到底发生了什么,但在我的日志中,我到达了这样的地步:“从本地数据库检索 %@ 对象的列表 - 得到x 结果。”,然后当应用程序崩溃时,日志记录将重新开始。在此 RKManagedObjectRequestOperation 中间的某个位置并返回更新的列表时,应用程序崩溃了大约 1/1000 次...

下面是我从 Crashlytics 获得的堆栈跟踪之一。有许多函数调用“更新函数”,有些在后台,有些在前台,但所有堆栈跟踪都引用此“更新函数”,您可以在下面的第 9 行中看到它 (updateAndFetchInfoWithCompletionHandler):

    Thread : com.apple.uikit.backgroundTaskAssertionQueue
0  libsystem_kernel.dylib         0x38911a50 mach_msg_trap + 20
1  libsystem_kernel.dylib         0x3891184d mach_msg + 40
2  SpringBoardServices            0x34d2b42d SBGetBackgroundTimeRemaining + 52
3  SpringBoardServices            0x34d29461 SBSGetBackgroundTimeRemaining + 36
4  UIKit                          0x30685b23 __40-[UIApplication backgroundTimeRemaining]_block_invoke + 10
5  libdispatch.dylib              0x38858d3f _dispatch_client_callout + 22
6  libdispatch.dylib              0x3885d6c3 _dispatch_barrier_sync_f_invoke + 26
7  UIKit                          0x30685a97 -[UIApplication backgroundTimeRemaining] + 182
8  <redacted>                     0x002345df __46-[LocationManager handleExitedRegion]_block_invoke_2 (LocationManager.m:262)
9  <redacted>                     0x002451e3 __57-[DataManager updateAndFetchInfoWithCompletionHandler:]_block_invoke (DataManager.m:719)
10 <redacted>                     0x00340d0d __66-[RKObjectRequestOperation setCompletionBlockWithSuccess:failure:]_block_invoke229 (RKObjectRequestOperation.m:506)
11 libdispatch.dylib              0x38858d53 _dispatch_call_block_and_release + 10
12 libdispatch.dylib              0x38858d3f _dispatch_client_callout + 22
13 libdispatch.dylib              0x3885b6c3 _dispatch_main_queue_callback_4CF + 278
14 CoreFoundation                 0x2dba3681 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
15 CoreFoundation                 0x2dba1f4d __CFRunLoopRun + 1308
16 CoreFoundation                 0x2db0c769 CFRunLoopRunSpecific + 524
17 CoreFoundation                 0x2db0c54b CFRunLoopRunInMode + 106
18 GraphicsServices               0x32a796d3 GSEventRunModal + 138
19 UIKit                          0x3046b891 UIApplicationMain + 1136
20 <redacted>                     0x000a3197 main (main.m:18)

这里是否有一些明显的我遗漏的东西导致了所有这些崩溃?

编辑:更改了上面的代码以在注释后反射(reflect)不同的托管对象上下文。

最佳答案

您不应该使用 persistentStoreManagedObjectContext。如果此代码在主线程上运行,那么您必须使用主队列上下文。如果在任意后台线程上运行,那么您必须专门为该调用创建一个新上下文。

上下文是特定于线程的,您必须尊重您创建的每个上下文的线程所有权。

在后台线程上运行时,使用 newChildManagedObjectContextWithConcurrencyType:tracksChanges: 创建一个新上下文.这维护了上下文所需的线程限制。

关于ios - RKManagedObjectRequestOperation objc_msgSend 期间 RestKit 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23300874/

相关文章:

objective-c - 无法以编程方式从 UITableView 中删除行

iphone - 我怎样才能画出弯曲的阴影?

objective-c - 使用 Apple Search API 按流派搜索?

ios - Objective-C - TableView Controller - 预期的表达

swift - NSPredicate 可以使用不区分大小写的搜索与 Core Data IN 比较吗? ( swift 4)

ios - 区 block 完成状态验证

iphone - 如何写UIImage?

ios - IOS 新手,我手机上的应用程序与模拟器不同

ios - 将 XML 数据解析为核心数据

ios - 将从核心数据中获取的数据分配给 UIPickerView