gpt4 book ai didi

ios - 使用 performBlock 进行计数请求时核心数据崩溃

转载 作者:行者123 更新时间:2023-12-01 16:52:03 24 4
gpt4 key购买 nike

使用 performBlock 在同一个私有(private)队列 NSManagedObjectContext 上同时调用 countForFetchRequest 两次时,我的 iOS 应用程序崩溃。

我像这样设置我的 childContext

_childContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_childContext setParentContext:self.managedObjectContext];

这是我调用 countForFetchRequest 的 performBlock
[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);
}
}];

这是崩溃日志:
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

我是否正确使用了 performBlock?

编辑:更多细节

performBlock 在 webViewDidFinishLoad:webView 委托(delegate)方法中被调用。我有多个 UIWebViews,当它们完成加载时,它们调用委托(delegate)方法,该方法又调用 performBlock 以查看它是否需要将 url 添加到核心数据数据库。

最佳答案

您可以将导致崩溃的方法封装在:

@synchronized(self) {
[object yourMethod];
}

这将确保即使在多线程时,内部的代码也将一次只运行一次......其他线程将只需要等待。坦率地说,这只有在崩溃的原因是并发时才有效。

关于ios - 使用 performBlock 进行计数请求时核心数据崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14857006/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com