Core Data многопоточность - PullRequest
       18

Core Data многопоточность

1 голос
/ 14 апреля 2010

Мое приложение начинается с представления табличного представления, источником данных которого является хранилище Core Data SQLite. Когда приложение запускается, создается вторичный поток с собственным контроллером хранилища и контекстом для получения обновлений из Интернета для данных в хранилище. Однако любые результирующие изменения в хранилище не уведомляются контроллером fetchedresults (я полагаю, потому что у него есть свой собственный координатор), и, следовательно, таблица не обновляется с изменениями хранилища. Какой самый эффективный способ обновить контекст в главном потоке? Я рассматриваю возможность отслеживания идентификаторов объектов любых объектов, измененных во вторичном потоке, отправки их в основной поток после завершения вторичного потока и вызова "[context refreshObject: ....].

Ответы [ 2 ]

2 голосов
/ 14 апреля 2010

Непрощенный ответ не обрабатывает потоки правильно.В частности, в документации говорится (выделено мое):

Если ваше приложение имеет графический интерфейс пользователя, рекомендуется получать события, связанные с пользователем, и инициировать обновления интерфейса из основного потока приложения.Такой подход помогает избежать проблем синхронизации, связанных с обработкой пользовательских событий и содержимым окна рисования. Некоторые платформы, такие как Какао, обычно требуют такого поведения , но даже для тех, которые этого не делают, сохранение этого поведения в главном потоке имеет преимущество, заключающееся в упрощении логики управления вашим пользовательским интерфейсом.1007 *

Наблюдатель за уведомлением будет уволен из любой ветки, в которой было размещено уведомление.Таким образом, вы не можете вызывать NSTableView reloadData напрямую из уведомления, отправленного фоновым потоком.

Нет необходимости использовать уведомления вообще.В фоновом потоке, когда будете готовы обновить пользовательский интерфейс, используйте любой из нескольких механизмов для перезагрузки данных в главном потоке - в потоке, который управляет основным циклом событий и пользовательским интерфейсом.

[tableView performSelectorOnMainThread: @selector(reloadData)
           withObject: nil waitUntilDone: YES];

Вы также можете использовать Grand Central Dispatch или NSOperation, чтобы сделать нечто подобное.

2 голосов
/ 14 апреля 2010

В вашей NSFetchedResultsController обработке таблицы зарегистрируйтесь в viewDidLoad или loadView для уведомления:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:@"ContextDidSave" object:nil];

Когда вторичный поток готов с новыми данными, просто сохраните контекст как обычно, а затем опубликуйте уведомление:

[[NSNotificationCenter defaultCenter] postNotificationName:@"ContextDidSave" object:managedObjectContext];

Уведомление будет обработано в вашем NSFetchedResultsController следующим способом:

РЕДАКТИРОВАТЬ : модифицированный метод, приведенный ниже, корректно учитывает многопоточность после глубокого обсуждения с bbum.

- (void)contextDidSave:(NSNotification *)notification
{

    SEL selector = @selector(mergeChangesFromContextDidSaveNotification:);
    [[[[UIApplication sharedApplication] delegate] managedObjectContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES];

}

Для обновления пользовательского интерфейса это можно сделать автоматически, используя NSFetchedResultsController методы делегата.

Наконец, не забудьте добавить в dealloc метод NSFetchedResultsController следующее:

[[NSNotificationCenter defaultCenter] removeObserver:self];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...