Использование основных данных одновременно и надежно

Я создаю свое первое приложение для iOS, которое теоретически должно быть довольно простым, но мне трудно сделать его достаточно пуленепробиваемым, чтобы я чувствовал себя уверенно, отправляя его в App Store.

Вкратце, главный экран имеет табличное представление, после выбора строки он переходит к другому табличному представлению, которое отображает информацию, относящуюся к выбранной строке, в режиме мастер-детализации. Базовые данные извлекаются в виде данных JSON из веб-службы один раз в день, а затем кэшируются в хранилище базовых данных. Данные, предшествующие этому дню, удаляются, чтобы предотвратить бесконечный рост файла базы данных SQLite. Все операции с сохранением данных выполняются с использованием Core Data, сNSFetchedResultsController подкрепление подробного табличного представления.

Проблема, с которой я сталкиваюсь, заключается в том, что если вы быстро переключаетесь между главным и подробным экранами несколько раз, когда свежие данные извлекаются, анализируются и сохраняются, приложение полностью зависает или вылетает. Кажется, что существует какое-то состояние гонки, возможно, из-за того, что Core Data импортирует данные в фоновом режиме, пока основной поток пытается выполнить выборку, но я предполагаю. У меня возникли проблемы с получением какой-либо значимой информации о сбое, обычно это SIGSEGV глубоко в стеке Core Data.

В таблице ниже показан фактический порядок событий, которые происходят при загрузке контроллера подробного табличного представления:

Main Thread                          Background Thread
viewDidLoad

                                     Get JSON data (using AFNetworking)

Create child NSManagedObjectContext (MOC)

                                     Parse JSON data
                                     Insert managed objects in child MOC
                                     Save child MOC
                                     Post import completion notification

Receive import completion notification
Save parent MOC
Perform fetch and reload table view

                                     Delete old managed objects in child MOC
                                     Save child MOC
                                     Post deletion completion notification

Receive deletion completion notification
Save parent MOC

Как только блок завершения AFNetworking запускается, когда поступают данные JSON,NSManagedObjectContext создается и передается «импортеру»; объект, который анализирует данные JSON и сохраняет объекты в хранилище базовых данных. Импортер выполняет с использованием новогоperformBlock Метод, представленный в iOS 5:

NSManagedObjectContext *child = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [child setParentContext:self.managedObjectContext];        
    [child performBlock:^{
        // Create importer instance, passing it the child MOC...
    }];

Объект импортера наблюдает за своими собственными МОСNSManagedObjectContextDidSaveNotification и затем отправляет свое собственное уведомление, которое наблюдается контроллером представления таблицы подробностей. Когда это уведомление публикуется, контроллер табличного представления выполняет сохранение на своей (родительской) MOC.

Я использую тот же самый базовый шаблон с «удалением» объект для удаления старых данных после импорта новых данных за день. Это происходит асинхронно после того, как новые данные были получены контроллером полученных результатов, и представление таблицы подробностей было перезагружено.

Одна вещь, которую я не делаю, это наблюдение за любыми уведомлениями о слиянии или блокировка любого из контекстов управляемого объекта или координатора постоянного хранилища. Это то, что я должен делать? Я немного не уверен, как правильно все это спроектировать, поэтому буду признателен за любые советы.

Ответы на вопрос(4)

Ваш ответ на вопрос