2015-04-10 4 views
2

После обновления устройства/xCode до iOS 8.3 мое приложение начинает сбой при выполнении обновления фона. Вот мой метод managedObjectContext/persistentStoreCoordinator:Многопоточная сбой CoreData на iOS 8.3

- (NSManagedObjectContext *)managedObjectContext { 
    NSThread *thisThread = [NSThread currentThread]; 
    if (thisThread == [NSThread mainThread]) { 
     return self.mainContext; 
    } 

    NSString * threadKey = [NSString stringWithFormat:@"%p", thisThread]; 
    NSManagedObjectContext * threadContext = nil; 
    @synchronized(self.managedObjectContexts) { 
     threadContext = self.managedObjectContexts[threadKey]; 
    } 

    if (!threadContext) { 
     threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     threadContext.parentContext = self.mainContext; 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:threadContext]; 

     @synchronized(self.managedObjectContexts) { 
      [self.managedObjectContexts setObject:threadContext forKey:threadKey]; 
     } 
    } 

    return threadContext; 
} 

+ (NSString*)managedObjectContextKeyForThread:(NSThread*)thread { 
return [NSString stringWithFormat:@"%i", (int)thread]; 
} 

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
if (!persistentStoreCoordinator) { 
    NSManagedObjectModel *objectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL]; 

    if(objectModel) { 
     NSPersistentStoreCoordinator *storeCoordinator = [[NSPersistentStoreCoordinator alloc] 
                  initWithManagedObjectModel:objectModel]; 
     NSDictionary * options = @{NSMigratePersistentStoresAutomaticallyOption : @(YES), 
            NSInferMappingModelAutomaticallyOption : @(YES) 
            }; 
     NSError* error = nil; 
     if ([storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL 
               options:options error:&error]) 
     { 
      persistentStoreCoordinator = storeCoordinator; 
     } else { 
      NSError *err = nil; 
      [[NSFileManager defaultManager] removeItemAtURL:self.storeURL error:&err]; 
      if ([storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL 
                options:options error:&error]) 
      { 
       [[NSNotificationCenter defaultCenter] postNotificationName:kDatabaseRecreatedNotificationKey object:nil]; 
       persistentStoreCoordinator = storeCoordinator; 
      } 
     } 
    } 
} 

return persistentStoreCoordinator; 
} 

Это происходит сбой в методе contextDidSave с сообщением об ошибке:

crash

В первой контрольной точке исключения в Debug Navigator он показывает еще одну строку - " developerSubmittedBlockToNSManagedObjectContextPerform "

Что не так с моим кодом? Он работал отлично до 8.3. Возможно, Apple добавила новые правила? Спасибо за помощь.

+0

Я не уверен, в чем причина вашей проблемы. Но для каждого потока вам не нужен отдельный контекст управляемого объекта, это устаревший подход от iOS <5. Теперь вы можете использовать только два контекста: один с «NSMainQueueConcurrencyType», который будет использоваться из основного потока и другого (родительский контекст) с помощью 'NSPrivateQueueConcurrencyType' для фоновой обработки. Затем вы можете просто использовать метод 'executeBlock' в контексте, чтобы убедиться, что все выполняется в правильном потоке. Эта статья может быть полезна: http://martiancraft.com/blog/2015/03/core-data-stack/ –

ответ

0

Это случилось со мной, а также с выпуском 8.3. Если ваш случай похож на мой, вы устанавливаете self.mainContext в viewDidLoad (вы не указали, где установлен этот ivar). Но я вижу в отладчике, что fetchedResultsController теперь вызывается перед viewDidLoad. Мое решение состояло в том, чтобы переместить настройку моего эквивалента self.mainContext в метод init, в моем случае initWithCoder.

+0

К сожалению, это не мой случай. Первоначальная инициализация mainContext в методе applicationDidFinishLaunchingWithOptions. – landonandrey

0

После много работы и головной боли я переехал в Magical Record library и достиг своей главной цели - обновления фоновых данных с помощью Core Data.