Безопасность CoreData и потоков

У меня есть одноэлементное имя CoreDataManager котором зарегистрирован mergeContextChangesForNotification :

 + (id) sharedManager{ static CoreDataManager *mSharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ mSharedManager = [[CoreDataManager alloc] init]; }); return mSharedManager; } - (id)init { self = [super init]; if (self) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChangesForNotification:) name:NSManagedObjectContextDidSaveNotification object:nil]; }); } return self; } 

после получения уведомления:

 - (void)mergeContextChangesForNotification:(NSNotification *)notification { [shareContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES]; } 

У меня есть два вопроса:

  1. Должен ли я использовать performSelectorOnMainThread здесь? так как в этом ответе говорится, что никогда. Я должен изменить его на GCD и использовать dispatch_get_main_queue ??
  2. mergeContextChangesForNotification ли регистрация mergeContextChangesForNotification в init является хорошей практикой для обеспечения того, чтобы уведомление всегда регистрировалось в основном потоке? который я прочитал из этого ответа

2 Solutions collect form web for “Безопасность CoreData и потоков”

При использовании типов параллелизма управляемых объектов, представленных в iOS 5 / OS X 10.7, предпочтительно использовать методы performBlock для обеспечения выполнения операции Core Data в правом потоке (точнее: в правой очереди).

Таким образом, вы создадите общий контекст с помощью

 shareContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 

и слияние изменений из других контекстов с

 - (void)mergeContextChangesForNotification:(NSNotification *)notification { [shareContext performBlock:^{ [shareContext mergeChangesFromContextDidSaveNotification:notification]; }]; } 

Также обратите внимание, что (как указано в документации NSManagedObjectContext ), рекомендуется регистрироваться для сохранения уведомлений только из известных контекстов. С object:nil в вашей регистрации вы можете получить неожиданные уведомления, потому что системные фреймворки используют Core Data внутренне.

Поэтому вы должны либо зарегистрироваться только для создаваемых вами контекстов. Кроме того, вы можете проверить, что уведомление было отправлено из контекста с тем же постоянным координатором хранилища:

 - (void)mergeContextChangesForNotification:(NSNotification *)notification { NSManagedObjectContext *otherContext = [notification object]; if (otherContext != shareContext && [otherContext persistentStoreCoordinator] == [shareContext persistentStoreCoordinator]) { [shareContext performBlock:^{ [shareContext mergeChangesFromContextDidSaveNotification:notification]; }]; } } 

Наконец, метод уведомления всегда вызывается в потоке, на котором он был отправлен . Неважно, в каком потоке зарегистрировано уведомление. Поэтому отправка регистрации в основной поток не требуется.

Проверьте пример приложения TopSongs , имейте в виду, что они не идеальны, но большую часть времени можно использовать для справки. Они синхронизируют вызовы mergeChangesFromContextDidSaveNotification должны выполняться только в основном потоке, но делая это немного более элегантным способом:

 // This method will be called on a secondary thread. Forward to the main thread for safe handling of UIKit objects. - (void)importerDidSave:(NSNotification *)saveNotification { if ([NSThread isMainThread]) { [self.managedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification]; [self.songsViewController fetch]; } else { [self performSelectorOnMainThread:@selector(importerDidSave:) withObject:saveNotification waitUntilDone:NO]; } } 

Что касается инициализации, то -init будет вызываться в том же потоке, на +sharedManager был вызван +sharedManager .

Кроме того, поскольку второй ответ, который вы связали, не очень информативен с точки зрения документации, позвольте мне оставить ссылку на раздел « Параллелизм с основными данными » в документах.

Interesting Posts

UIActivityViewController включает, а не исключает типы операций

Как сохранить приложение в фоновом режиме в фоновом режиме?

Бутстрап-колонки с flexbox не занимают должной ширины на iOS и Safari

Как вы используете оболочку связки ключей для слесаря

Компиляция внешней библиотеки C ++ для использования с проектом iOS

Пользовательское усечение UITextView

Запись видео в iOS с помощью MonoTouch

Внутреннее отображение в iOS

Как сделать абстрактные объекты в Realm.io в Swift

Вы не имеете права использовать эту услугу для провайдера

Неверный размер-класс UIViewController, показанный с помощью UIPopoverController

Как получить размер шрифта и имя шрифта UILabel?

Какое разрешение dpi используется для iPhone App?

Пользовательский контейнерный контроллер: переходFromViewController: просмотр не выполняется должным образом перед анимацией

Где подключается средство связи линии связи Prefpane в OSX Mountain Lion и Xcode 4.4

PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.