[英]Core Data crashing when doing count request using performBlock
My iOS app is crashing when doing two calls to countForFetchRequest at the same time on the same private queue NSManagedObjectContext using performBlock. 使用performBlock在同一私有队列NSManagedObjectContext上同时对countForFetchRequest进行两次调用时,我的iOS应用程序崩溃。
I setup my childContext like this 我这样设置了我的childContext
_childContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_childContext setParentContext:self.managedObjectContext];
And this is my performBlock that calls countForFetchRequest 这是我的performBlock,它调用countForFetchRequest
[self.childContext performBlock:^{
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"History"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"url == %@", url];
NSError *error = nil;
NSUInteger num = [self.childContext countForFetchRequest:fetchRequest error:&error];
if(error != nil){
NSLog(@"Error getting count for history url %@ %@", url, error);
return;
}
if(num > 0){ // Already have this in the history, don't re-add it
return;
}
History *history = (History *)[NSEntityDescription insertNewObjectForEntityForName:@"History" inManagedObjectContext:self.childContext];
history.url = url;
history.title = title;
if(![self.childContext save:&error]){
NSLog(@"Error occurred saving history item %@ %@ %@", title, url, error);
}
}];
And here is the crash log: 这是崩溃日志:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x3a427350 __pthread_kill + 8
1 libsystem_c.dylib 0x3a39e11e pthread_kill + 54
2 libsystem_c.dylib 0x3a3da96e abort + 90
3 libc++abi.dylib 0x39978d4a abort_message + 70
4 libc++abi.dylib 0x39975ff4 default_terminate() + 20
5 libobjc.A.dylib 0x39f29a74 _objc_terminate() + 144
6 libc++abi.dylib 0x39976078 safe_handler_caller(void (*)()) + 76
7 libc++abi.dylib 0x39976110 std::terminate() + 16
8 libc++abi.dylib 0x39977594 __cxa_rethrow + 84
9 libobjc.A.dylib 0x39f299cc objc_exception_rethrow + 8
10 CoreData 0x31e868e0 -[NSManagedObjectContext(_NSInternalAdditions) _countWithNoChangesForRequest:error:] + 764
11 CoreData 0x31e833fe -[NSManagedObjectContext countForFetchRequest:error:] + 1062
12 CoreData 0x31e92470 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke_0 + 460
13 libdispatch.dylib 0x3a345d26 _dispatch_barrier_sync_f_slow_invoke + 82
14 libdispatch.dylib 0x3a3404b4 _dispatch_client_callout + 20
15 libdispatch.dylib 0x3a3451b8 _dispatch_main_queue_callback_4CF$VARIANT$mp + 220
16 CoreFoundation 0x3205cf36 __CFRunLoopRun + 1286
17 CoreFoundation 0x31fcfeb8 CFRunLoopRunSpecific + 352
18 CoreFoundation 0x31fcfd44 CFRunLoopRunInMode + 100
19 GraphicsServices 0x35b992e6 GSEventRunModal + 70
20 UIKit 0x33ee52fc UIApplicationMain + 1116
21 Accountable2You Mobile 0x000e5d28 0xe4000 + 7464
22 Accountable2You Mobile 0x000e5cc4 0xe4000 + 7364
Thread 1 name: Dispatch queue: NSManagedObjectContext Queue
Thread 1:
0 libsystem_kernel.dylib 0x3a416f04 semaphore_wait_trap + 8
1 libdispatch.dylib 0x3a3462fc _dispatch_thread_semaphore_wait$VARIANT$mp + 8
2 libdispatch.dylib 0x3a34487c _dispatch_barrier_sync_f_slow + 96
3 CoreData 0x31e82df2 _perform + 166
4 CoreData 0x31e921c6 -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] + 238
5 CoreData 0x31e86770 -[NSManagedObjectContext(_NSInternalAdditions) _countWithNoChangesForRequest:error:] + 396
6 CoreData 0x31e833fe -[NSManagedObjectContext countForFetchRequest:error:] + 1062
7 Accountable2You Mobile 0x000ee7be 0xe4000 + 42942
8 CoreData 0x31e86072 developerSubmittedBlockToNSManagedObjectContextPerform_privateasync + 66
9 libdispatch.dylib 0x3a344eca _dispatch_queue_drain$VARIANT$mp + 138
10 libdispatch.dylib 0x3a344dbc _dispatch_queue_invoke$VARIANT$mp + 36
11 libdispatch.dylib 0x3a34591a _dispatch_root_queue_drain + 182
12 libdispatch.dylib 0x3a345abc _dispatch_worker_thread2 + 80
13 libsystem_c.dylib 0x3a375a0e _pthread_wqthread + 358
14 libsystem_c.dylib 0x3a3758a0 start_wqthread + 4
Am I using the performBlock correctly? 我是否正确使用performBlock?
Edit: More details 编辑:更多详细信息
The performBlock is being called in a webViewDidFinishLoad:webView delegate method. 在webViewDidFinishLoad:webView委托方法中调用performBlock。 I have multiple UIWebViews and when they finish loading they are calling the delegate method which is in turn calling the performBlock to see if it needs to add the url to the core data database. 我有多个UIWebViews,当它们完成加载时,它们正在调用委托方法,该方法又依次调用performBlock以查看是否需要将url添加到核心数据数据库中。
You can encapsulate the method causing the crash in: 您可以将导致崩溃的方法封装在:
@synchronized(self) {
[object yourMethod];
}
This will make sure that even while multithreading, the piece of code inside will be running just once at a time ... other threads will just have to wait. 这样可以确保即使在多线程处理中,其中的代码一次也只能运行一次……其他线程将只需要等待。 Frankly, this will work only if the cause of the crash is the concurrency. 坦白说,只有当崩溃的原因是并发时,这才起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.