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

Я создаю свое первое приложение для 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...
    }];

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

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

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

7
задан John Topley 23 July 2012 в 15:03
поделиться