核心数据在后台线程中锁定

核心数据在后台线程中锁定

本文介绍了核心数据在后台线程中锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我在Core Data中收到锁。我真的不明白的原因。因为我在后台线程中创建一个后台MOC。下面你可以看到什么堆栈跟踪(我暂停应用程序的执行)看起来像这样发生时: 1,Queue:com.apple.main-thread #0 0x32d2a0fc in __psynch_mutexwait()#1 0x3608b128 in pthread_mutex_lock()#2 0x365d2dac in - [_ PFLock lock] ()#3 0x365e3264 in - [NSPersistentStoreCoordinator executeRequest:withContext:error:]()#4 0x365e1e2a in - [NSManagedObjectContext executeFetchRequest:error:]()#5 0x3664a93e in - NSManagedObjectContext(_NestedContextSupport)_parentObjectsForFetchRequest:inContext:error:]()#6 0x3664b0c8 in __82- [NSManagedObjectContext(_NestedContextSupport)executeRequest:withContext:error:] _ block_invoke_0()#7 0x3932bd28 in _dispatch_barrier_sync_f_slow_invoke b $ b线程10,队列:EventKitHelperSyncSerialBackgroundQueue #0 0x32d19f04 in semaphore_wait_trap()#1 0x3932c300在_dispatch_thread_semaphore_wait $ VARIANT $ mp()#2 0x3932a880 in _dispatch_barrier_sync_f_slow()#3 0x3663b9e6 in _perform()#4 0x3664adba in - [NSManagedObjectContext(_NestedContextSupport)executeRequest:withContext:error:]()#5 0x365e1e2a - [NSManagedObjectContext executeFetchRequest:error:]()#6 0x000b11e4 in - [CoreDataHelper fetchEntity:predicate:andSortDescriptors:inManagedObjectContext:] at /Users/peterwarbo/Desktop/app/CoreDataHelper.m:110 # 7 0x000ad648 in - [EventKitHelper processChangedCalendar] at /Users/peterwarbo/Desktop/app/EventKitHelper.m:242 #8 0x000ad3b4在__54- [EventKitHelper syncInBackgroundWithCompletionBlock:] _ block_invoke_0在/ Users / peterwarbo / Desktop / app / EventKitHelper .m:218 #9 0x3932711e在_dispatch_call_block_and_release()#10 0x3932aece在_dispatch_queue_drain $ VARIANT $ mp()#11 0x3932adc0在_dispatch_queue_invoke $ VARIANT $ mp()# 12 0x3932b91c在_dispatch_root_queue_drain()#13 0x3932bac0在_dispatch_worker_thread2()#14 0x36090a10在_pthread_wqthread()#15 0x360908a4在start_wqthread() 在 EventKitHelperSyncSerialBackgroundQueue 中,我在后台队列中执行一些Core Data处理。 提醒的是 NSManagedObject 。 $ b EventKitHelper.m - (void)syncInBackgroundWithCompletionBlock:(CalendarSyncCompletionBlock)block { DLogName() self。 completionBlock = block; if(self.syncSerialBackgroundQueue == NULL){ self.syncSerialBackgroundQueue = dispatch_queue_create(EventKitHelperSyncSerialBackgroundQueue,0); } dispatch_async(self.syncSerialBackgroundQueue,^ { [self processChangedCalendar]; }); } - (void)processChangedCalendar { DLogName() CoreDataHelper * cdHelper = [CoreDataHelper sharedInstance]; //存储已更改,事件可以更新/删除/添加 //需要检查用户创建的提醒是否正在引用日历 //如果因此,更新受影响的提醒 //仅提取谓词类型(RMReminderDateServiceCalendarEvent或RMReminderDateServiceCalendarBirthday)的AND状态未完成的提醒 NSPredicate * userRemindersPredicate = [NSPredicate predicateWithFormat:@ dateService ==%@ OR dateService ==%@)AND status!=%@,@(RMReminderDateServiceCalendarEvent),@(RMReminderDateServiceCalendarBirthday),@(RMReminderStatusCompleted)]; //以最早的日期开头排序用户的提醒 NSSortDescriptor * dateSortAsc = [NSSortDescriptor sortDescriptorWithKey:@dateascending:YES]; //为线程安全创建一个新的MOC NSManagedObjectContext * syncContext = [cdHelper threadedManagedObjectContext]; self.syncContext = syncContext; NSArray * usersReminders = [[CoreDataHelper sharedInstance] fetchEntity:APReminderEntity谓词:userRemindersPredicate和SortDescriptors:@ [dateSortAsc] inManagedObjectContext:syncContext]; if(usersReminders.count == 0){ DLog(@用户没有任何日历提醒,无需同步) BOOL error = NO; self.completionBlock(error); return; } else { if(!self.isCalendarAccessAuthorized){ DLog(@日历访问未授权,我们有日历提醒,警告用户) BOOL错误= YES; self.completionBlock(error); return; } else { DLog(@日历访问已授权)} } 如果self.calendarchanged){ DLog(@日历未更新,无需同步) BOOL错误= NO; self.completionBlock(error); return; } DLog(@Calendar updated,syncing ...) NSDate * earliestReminderDate = [(Reminder *)[usersReminders objectAtIndex:0] date ]; //由于存在日历事件可以改变日期的可能性,我们应该从我们最早的提醒日期+ 1年前获取事件 NSDate * eventsFromThisDate = [Utilities oneYearAgoForDate:[Utilities midnightDateForDate:earliestReminderDate]]; NSDate * endDate = [NSDate distantFuture]; //这将让我事件4年以后 //创建谓词 NSPredicate * eventStorePredicate = [self.eventStore predicateForEventsWithStartDate:eventsFromThisDate endDate:endDate calendars:nil]; //获取与谓词匹配的所有事件。 NSArray * eventKitEvents = [self.eventStore eventsMatchingPredicate:eventStorePredicate]; NSMutableArray * events = [NSMutableArray arrayWithCapacity:100]; for(EKEvent * event in eventKitEvents){ NSString * eventTitle = [event title]; NSDate * eventDate = [event startDate]; NSDate * eventDateModified = [event lastModifiedDate]; NSString * eventID = [event eventIdentifier]; //检查事件是否为生日事件 BOOL isBirthday = [event birthdayPersonID]!= -1? YES:NO; RMReminderDateService dateService; if(isBirthday){ dateService = RMReminderDateServiceCalendarBirthday; } else { dateService = RMReminderDateServiceCalendarEvent; } RMDateEvent * calendarEvent = [[RMDateEvent alloc] initWithDate:eventDate dateModified:eventDateModified name:eventTitle dateService:dateService andID:eventID]; BOOL eventAlreadyAdded = NO; if(!eventAlreadyAdded){ [events addObject:calendarEvent]; } } (usersReminders中的提醒*提醒){ NSPredicate * predicateID = [NSPredicate predicateWithFormat:@ID ==%@ ,reminder.dateServiceID]; NSArray * eventsMatchingID = [events filteredArrayUsingPredicate:predicateID]; RMDateEvent * event = [eventsMatchingID lastObject]; if(event == nil){ //我们找不到ID的事件,尝试按日期和标题找到它 NSPredicate * predicateDateAndTitle = [NSPredicate predicateWithFormat:@date ==%@ AND name ==%@,reminder.date,reminder.dateText]; NSArray * eventsMatchingDateAndTitle = [events filteredArrayUsingPredicate:predicateDateAndTitle]; event = [eventsMatchingDateAndTitle lastObject]; if(event == nil){ //我们找不到事件,很可能是从用户的事件中删除了,或者用户已经改变了所有保存事件的值:-( } else { //根据日期和标题找到它 [self processReminder:reminder forDateEvent:event]; } } else { //我们通过ID 找到它[self processReminder:Reminder forDateEvent:event]; } } [self fetchEventsFromNow]; [self processEventKitEvents]; #warning TODO:广播消息以更新提醒日期 AppDelegate * appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate]; [appDelegate setTabCountInBackground]; self.calendarchanged = NO; DLog @日历同步已完成) BOOL错误= NO; self.completionBlock(error); } - (void)processReminder:(Reminder *)提醒forDateEvent:(RMDateEvent *)event { NSDate * eventModifiedDate = [event dateModified]; if([eventModifiedDate compare:reminder.dateModified] == NSOrderedDescending){ //此事件已修改 //最重要的是检查如果更改的事件日期已过 NSDate * today = [NSDate date]; if([today compare:event.date] == NSOrderedDescending){ //事件日期已过 if(reminder.isRepeating ){ //我们取消UILocalNotification并重新安排一个新的UILocalNotification,下一个提醒日期状态也设置为过期 NSDate * reminderDate = [Utilities reminderDateFromDate:event.date andTime:reminder.date]; //取消UILocalNotification [Utilities cancelUILocalNotificationForReminder:reminder]; reminder.status = @(RMReminderStatusOverdue); reminder.date = reminderDate; reminder.dateModified = event.dateModified; reminder.dateServiceID = event.ID; reminder.dateText = event.name; NSDate * nextReminderDate = [实用程序nextReminderDateFromNowForReminder:提醒]; reminder.date = nextReminderDate; //重新安排提醒 [Utilities scheduleUILocalNotificationForReminder:reminder]; //我们改回这个旧的提醒日期以反映过期状态 reminder.date = reminderDate; [[CoreDataHelper sharedInstance] saveInManagedObjectContext:self.syncContext]; } else { //我们应取消此提醒的UILocalNotification并将此提醒的状态设置为过期 NSDate * reminderDate = [Utilities reminderDateFromDate:event.date andTime:reminder.date]; //取消UILocalNotification [Utilities cancelUILocalNotificationForReminder:reminder]; reminder.status = @(RMReminderStatusOverdue); reminder.date = reminderDate; reminder.dateModified = event.dateModified; reminder.dateServiceID = event.ID; reminder.dateText = event.name; [[CoreDataHelper sharedInstance] saveInManagedObjectContext:self.syncContext]; } } else { //事件日期是未来 NSDate * reminderDate = [Utilities reminderDateFromDate:event。日期和时间:reminder.date]; //取消UILocalNotification [Utilities cancelUILocalNotificationForReminder:reminder]; reminder.status = @(RMReminderStatusUpcoming); reminder.date = reminderDate; reminder.dateModified = event.dateModified; reminder.dateServiceID = event.ID; reminder.dateText = event.name; [[CoreDataHelper sharedInstance] saveInManagedObjectContext:self.syncContext]; //重新安排提醒 [Utilities scheduleUILocalNotificationForReminder:reminder]; } } } CoreDataHelper.m - (NSArray *)fetchEntity:(NSString *)entity predicate:(NSPredicate *)predicate andSortDescriptors: NSArray *)sortDescriptors inManagedObjectContext:(NSManagedObjectContext *)context { DLogName() if(context == nil){ //使用default MOC context = self.managedObjectContext; } NSEntityDescription * entityDescription = [NSEntityDescription entityForName:entity inManagedObjectContext:context]; NSFetchRequest * request = [[NSFetchRequest alloc] init]; [request setEntity:entityDescription]; if(predicate!= nil){ [request setPredicate:predicate]; } if(sortDescriptors!= nil){ [request setSortDescriptors:sortDescriptors]; } NSError * error = nil; NSArray * entities = [context executeFetchRequest:request error:& error]; if(entities == nil){ DLog(@出现错误:%@,[error userInfo]); } 返回实体; } - (NSManagedObjectContext *)threadedManagedObjectContext { NSManagedObjectContext * threadedMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType]; threadedMoc.parentContext = self.managedObjectContext; return threadedMoc; } / ** 返回应用程序的受管对象上下文。 如果上下文不存在,则将创建该上下文并将其绑定到应用程序的持久存储协调器。 * / - (NSManagedObjectContext *)managedObjectContext { if(_managedObjectContext!= nil) { return _managedObjectContext } NSPersistentStoreCoordinator * coordinator = [self persistentStoreCoordinator]; if(coordinator!= nil) { // _ managedObjectContext = [[NSManagedObjectContext alloc] init]; _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; } - (void)saveInManagedObjectContext:(NSManagedObjectContext *)context { if(context == nil){ / /使用默认MOC context = self.managedObjectContext; NSError * error = nil; if(context!= nil) { if([context hasChanges]&&![context save:& error]) { / * 用代码来替换这个实现,以适当地处理错误。 abort()导致应用程序生成崩溃日志并终止。您不应在运送应用程序中使用此功能,但在开发过程中可能很有用。 * / DLog(@未解析的错误%@,%@,错误,[错误userInfo]); abort(); } } } else { NSError * error = nil; //第一个保存(子)上下文 if([context hasChanges]&&![context save:& error]) { / * 用代码替换此实现,以正确处理错误。 abort()导致应用程序生成崩溃日志并终止。您不应在运送应用程序中使用此功能,但在开发过程中可能很有用。 * / DLog(@未解析的错误%@,%@,错误,[错误userInfo]); abort(); } //然后保存父上下文 if([self.managedObjectContext hasChanges]) { / * 替换此实现用代码来正确处理错误。 abort()导致应用程序生成崩溃日志并终止。您不应在运送应用程序中使用此功能,但在开发过程中可能很有用。 * / [self.managedObjectContext performBlock:^ { NSError * parentError = nil; [self.managedObjectContext save:&parent; parentError]; if(parentError){ DLog(@未解析错误%@,%@,parentError,[parentError userInfo]); abort(); } }]; } } } 解决方案> 不完全确定这是否适用于你,但我得到类似的错误。我使用 NSPrivateQueueConcurrencyType 不是来解决这些问题。 放置 executeFetchRequest 在MOC的 performBlockAndWait 中。 所以在CoreDataHelper.m的fetchEntity方法你会有这样的: [context performBlockAndWait:^ { NSError * error = nil; NSArray * entities = [context executeFetchRequest:request error:& error]; }]; I'm getting locks in Core Data. I really don't understand the reason. Because I'm creating a background MOC when I'm processing in a background thread. Below you can see what a stack trace (I'm pausing the execution of the app) looks like when this happens:Thread 1, Queue : com.apple.main-thread#0 0x32d2a0fc in __psynch_mutexwait ()#1 0x3608b128 in pthread_mutex_lock ()#2 0x365d2dac in -[_PFLock lock] ()#3 0x365e3264 in -[NSPersistentStoreCoordinator executeRequest:withContext:error:] ()#4 0x365e1e2a in -[NSManagedObjectContext executeFetchRequest:error:] ()#5 0x3664a93e in -[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:] ()#6 0x3664b0c8 in __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke_0 ()#7 0x3932bd28 in _dispatch_barrier_sync_f_slow_invoke ()Thread 10, Queue : EventKitHelperSyncSerialBackgroundQueue#0 0x32d19f04 in semaphore_wait_trap ()#1 0x3932c300 in _dispatch_thread_semaphore_wait$VARIANT$mp ()#2 0x3932a880 in _dispatch_barrier_sync_f_slow ()#3 0x3663b9e6 in _perform ()#4 0x3664adba in -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] ()#5 0x365e1e2a in -[NSManagedObjectContext executeFetchRequest:error:] ()#6 0x000b11e4 in -[CoreDataHelper fetchEntity:predicate:andSortDescriptors:inManagedObjectContext:] at /Users/peterwarbo/Desktop/app/CoreDataHelper.m:110#7 0x000ad648 in -[EventKitHelper processChangedCalendar] at /Users/peterwarbo/Desktop/app/EventKitHelper.m:242#8 0x000ad3b4 in __54-[EventKitHelper syncInBackgroundWithCompletionBlock:]_block_invoke_0 at /Users/peterwarbo/Desktop/app/EventKitHelper.m:218#9 0x3932711e in _dispatch_call_block_and_release ()#10 0x3932aece in _dispatch_queue_drain$VARIANT$mp ()#11 0x3932adc0 in _dispatch_queue_invoke$VARIANT$mp ()#12 0x3932b91c in _dispatch_root_queue_drain ()#13 0x3932bac0 in _dispatch_worker_thread2 ()#14 0x36090a10 in _pthread_wqthread ()#15 0x360908a4 in start_wqthread ()In the EventKitHelperSyncSerialBackgroundQueue I'm doing some Core Data processing in a background queue. Reminders are NSManagedObjects. Sorry for the amount of code but I thought it's better to not leave out any important details.EventKitHelper.m- (void)syncInBackgroundWithCompletionBlock:(CalendarSyncCompletionBlock)block { DLogName() self.completionBlock = block; if (self.syncSerialBackgroundQueue == NULL) { self.syncSerialBackgroundQueue = dispatch_queue_create("EventKitHelperSyncSerialBackgroundQueue", 0); } dispatch_async(self.syncSerialBackgroundQueue, ^{ [self processChangedCalendar]; });}- (void)processChangedCalendar { DLogName() CoreDataHelper *cdHelper = [CoreDataHelper sharedInstance]; // Store has been changed, events could be updated/deleted/added // Need to check if any of the user created Reminders are referencing the calendar // If so, update the affected Reminders // Predicate to fetch only Reminders that are of type (RMReminderDateServiceCalendarEvent or RMReminderDateServiceCalendarBirthday) AND status is not completed NSPredicate *userRemindersPredicate = [NSPredicate predicateWithFormat:@"(dateService == %@ OR dateService == %@) AND status != %@", @(RMReminderDateServiceCalendarEvent), @(RMReminderDateServiceCalendarBirthday), @(RMReminderStatusCompleted)]; // Sort the user's Reminders with the earliest date first NSSortDescriptor *dateSortAsc = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]; // Creating a new MOC for thread safety NSManagedObjectContext *syncContext = [cdHelper threadedManagedObjectContext]; self.syncContext = syncContext; NSArray *usersReminders = [[CoreDataHelper sharedInstance] fetchEntity:APReminderEntity predicate:userRemindersPredicate andSortDescriptors:@[dateSortAsc] inManagedObjectContext:syncContext]; if (usersReminders.count == 0) { DLog(@"User doesn't have any Calendar Reminders, no need to sync") BOOL error = NO; self.completionBlock(error); return; } else { if (!self.isCalendarAccessAuthorized) { DLog(@"Calendar access is not authorized and we have Calendar Reminders, alert the user") BOOL error = YES; self.completionBlock(error); return; } else { DLog(@"Calendar access is authorized") } } if (!self.calendarchanged) { DLog(@"Calendar not updated, no need to sync") BOOL error = NO; self.completionBlock(error); return; } DLog(@"Calendar updated, syncing...") NSDate *earliestReminderDate = [(Reminder *) [usersReminders objectAtIndex:0] date]; // Since there exists a possibility that a Calendar event can change date back in time, we should fetch events from our earliest Reminder date + 1 year back NSDate *eventsFromThisDate = [Utilities oneYearAgoForDate:[Utilities midnightDateForDate:earliestReminderDate]]; NSDate *endDate = [NSDate distantFuture]; // This will get me events 4 years from now // Create the predicate NSPredicate *eventStorePredicate = [self.eventStore predicateForEventsWithStartDate:eventsFromThisDate endDate:endDate calendars:nil]; // Fetch all events that match the predicate. NSArray *eventKitEvents = [self.eventStore eventsMatchingPredicate:eventStorePredicate]; NSMutableArray *events = [NSMutableArray arrayWithCapacity:100]; for (EKEvent *event in eventKitEvents) { NSString *eventTitle = [event title]; NSDate *eventDate = [event startDate]; NSDate *eventDateModified = [event lastModifiedDate]; NSString *eventID = [event eventIdentifier]; // Check if event is a Birthday event BOOL isBirthday = [event birthdayPersonID] != -1 ? YES : NO; RMReminderDateService dateService; if (isBirthday) { dateService = RMReminderDateServiceCalendarBirthday; } else { dateService = RMReminderDateServiceCalendarEvent; } RMDateEvent *calendarEvent = [[RMDateEvent alloc] initWithDate:eventDate dateModified:eventDateModified name:eventTitle dateService:dateService andID:eventID]; BOOL eventAlreadyAdded = NO; if (!eventAlreadyAdded) { [events addObject:calendarEvent]; } } for (Reminder *reminder in usersReminders) { NSPredicate *predicateID = [NSPredicate predicateWithFormat:@"ID == %@", reminder.dateServiceID]; NSArray *eventsMatchingID = [events filteredArrayUsingPredicate:predicateID]; RMDateEvent *event = [eventsMatchingID lastObject]; if (event == nil) { // We couldn't find the event by ID, try to find it by date AND title NSPredicate *predicateDateAndTitle = [NSPredicate predicateWithFormat:@"date == %@ AND name == %@", reminder.date, reminder.dateText]; NSArray *eventsMatchingDateAndTitle = [events filteredArrayUsingPredicate:predicateDateAndTitle]; event = [eventsMatchingDateAndTitle lastObject]; if (event == nil) { // We couldn't find the event, most likely it has been deleted from the user's events or the user has changed all values for our saved event :-( } else { // We found it by date AND title [self processReminder:reminder forDateEvent:event]; } } else { // We found it by ID [self processReminder:reminder forDateEvent:event]; } } [self fetchEventsFromNow]; [self processEventKitEvents]; #warning TODO: Broadcast a message to update the Reminder date AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate]; [appDelegate setTabCountInBackground]; self.calendarchanged = NO; DLog(@"Calendar sync done") BOOL error = NO; self.completionBlock(error);}- (void)processReminder:(Reminder *)reminder forDateEvent:(RMDateEvent *)event { NSDate *eventModifiedDate = [event dateModified]; if ([eventModifiedDate compare:reminder.dateModified] == NSOrderedDescending) { // This event has been modified // Most important now is to check if the changed event date has passed NSDate *today = [NSDate date]; if ([today compare:event.date] == NSOrderedDescending) { // Event date has passed if (reminder.isRepeating) { // We cancel the UILocalNotification and reschedule a new UILocalNotification for the next Reminder date status also set to overdue NSDate *reminderDate = [Utilities reminderDateFromDate:event.date andTime:reminder.date]; // Cancel UILocalNotification [Utilities cancelUILocalNotificationForReminder:reminder]; reminder.status = @(RMReminderStatusOverdue); reminder.date = reminderDate; reminder.dateModified = event.dateModified; reminder.dateServiceID = event.ID; reminder.dateText = event.name; NSDate *nextReminderDate = [Utilities nextReminderDateFromNowForReminder:reminder]; reminder.date = nextReminderDate; // Re-schedule the Reminder [Utilities scheduleUILocalNotificationForReminder:reminder]; // We change back to this old Reminder date to reflect the overdue status reminder.date = reminderDate; [[CoreDataHelper sharedInstance] saveInManagedObjectContext:self.syncContext]; } else { // We should cancel the UILocalNotification for this Reminder and set the status for this Reminder to overdue NSDate *reminderDate = [Utilities reminderDateFromDate:event.date andTime:reminder.date]; // Cancel UILocalNotification [Utilities cancelUILocalNotificationForReminder:reminder]; reminder.status = @(RMReminderStatusOverdue); reminder.date = reminderDate; reminder.dateModified = event.dateModified; reminder.dateServiceID = event.ID; reminder.dateText = event.name; [[CoreDataHelper sharedInstance] saveInManagedObjectContext:self.syncContext]; } } else { // Event date is in the future NSDate *reminderDate = [Utilities reminderDateFromDate:event.date andTime:reminder.date]; // Cancel UILocalNotification [Utilities cancelUILocalNotificationForReminder:reminder]; reminder.status = @(RMReminderStatusUpcoming); reminder.date = reminderDate; reminder.dateModified = event.dateModified; reminder.dateServiceID = event.ID; reminder.dateText = event.name; [[CoreDataHelper sharedInstance] saveInManagedObjectContext:self.syncContext]; // Re-schedule the Reminder [Utilities scheduleUILocalNotificationForReminder:reminder]; } }}CoreDataHelper.m- (NSArray *)fetchEntity:(NSString *)entity predicate:(NSPredicate *)predicate andSortDescriptors:(NSArray *)sortDescriptors inManagedObjectContext:(NSManagedObjectContext *)context { DLogName() if (context == nil) { // Use default MOC context = self.managedObjectContext; } NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entity inManagedObjectContext:context]; NSFetchRequest *request = [[NSFetchRequest alloc] init]; [request setEntity:entityDescription]; if (predicate != nil) { [request setPredicate:predicate]; } if (sortDescriptors != nil) { [request setSortDescriptors:sortDescriptors]; } NSError *error = nil; NSArray *entities = [context executeFetchRequest:request error:&error]; if (entities == nil) { DLog(@"There was an error: %@", [error userInfo]); } return entities;}- (NSManagedObjectContext *)threadedManagedObjectContext { NSManagedObjectContext *threadedMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType]; threadedMoc.parentContext = self.managedObjectContext; return threadedMoc;}/** Returns the managed object context for the application. If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application. */- (NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext != nil) { return _managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { //_managedObjectContext = [[NSManagedObjectContext alloc] init]; _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext;}- (void)saveInManagedObjectContext:(NSManagedObjectContext *)context { if (context == nil) { // Use default MOC context = self.managedObjectContext; NSError *error = nil; if (context != nil) { if ([context hasChanges] && ![context save:&error]) { /* Replace this implementation with code to handle the error appropriately. abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. */ DLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } } } else { NSError *error = nil; // First save (child) context if ([context hasChanges] && ![context save:&error]) { /* Replace this implementation with code to handle the error appropriately. abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. */ DLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } // Then save parent context if ([self.managedObjectContext hasChanges]) { /* Replace this implementation with code to handle the error appropriately. abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. */ [self.managedObjectContext performBlock:^{ NSError *parentError = nil; [self.managedObjectContext save:&parentError]; if (parentError) { DLog(@"Unresolved error %@, %@", parentError, [parentError userInfo]); abort(); } }]; } }} 解决方案 Not totally sure if this applies to you but I was getting similar errors. I solved them byUsing NSPrivateQueueConcurrencyType not NSConfinementConcurrencyType to take processing off the main thread.Putting executeFetchRequest inside MOC's performBlockAndWait.So in CoreDataHelper.m's fetchEntity method you would have something like this:[context performBlockAndWait:^{ NSError *error = nil; NSArray *entities = [context executeFetchRequest:request error:&error];}]; 这篇关于核心数据在后台线程中锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
09-03 07:14