В нашем разрабатываемом приложении для хранения наших данных мы используем Core Data с резервным хранилищем sqlite.Объектная модель для нашего приложения сложна.Кроме того, общий объем данных, обслуживаемых нашим приложением, слишком велик, чтобы поместиться в пакет приложений для iOS (iPhone / iPad / iPod Touch).Из-за того, что наши пользователи, как правило, заинтересованы только в подмножестве данных, мы разбили наши данные таким образом, что приложение поставляется с подмножеством (хотя и ~ 100 МБ) объектов данных вкомплект приложений.Наши пользователи имеют возможность загружать дополнительные объекты данных (размером ~ 5–100 МБ) с нашего сервера после оплаты дополнительного содержимого через покупки в приложении iTunes.Файлы инкрементных данных (существующие в хранилищах sqlite) используют ту же версию xcdatamodel, что и данные, которые поставляются вместе с пакетом;в объектной модели изменений нет.Файлы инкрементных данных загружаются с нашего сервера в виде сжатых файлов sqlite.Мы не хотим раздувать наш пакет приложений, отправляя добавочное содержимое вместе с приложением.Кроме того, мы не хотим полагаться на запросы через веб-сервис (из-за сложной модели данных).Мы проверили загрузку инкрементных данных sqlite с нашего сервера.Мы смогли добавить загруженное хранилище данных в общий persistentStoreCoordinator приложения.
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:defaultStoreURL options:options error:&error])
{
NSLog(@"Failed with error: %@", [error localizedDescription]);
abort();
}
// Check for the existence of incrementalStore
// Add incrementalStore
if (incrementalStoreExists) {
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:incrementalStoreURL options:options error:&error])
{
NSLog(@"Add of incrementalStore failed with error: %@", [error localizedDescription]);
abort();
}
}
}
Однако есть две проблемы с этим:
- Результаты выборки данных (например, с NSFetchResultController) отображаются с данными из incrementalStoreURL, добавленными кконец данных из defaultStoreURL.
- Некоторые объекты дублируются.В нашей модели данных есть много объектов с данными только для чтения;они дублируются, когда мы добавляем второй persistentStore в persistentStoreCoordinator.
В идеале мы хотели бы, чтобы базовые данные объединяли графы объектов из двух постоянных хранилищ в одно (нет общих отношений между данными издва магазина на момент загрузки данных).Также мы хотели бы удалить дубликаты объектов.Ища в Интернете, мы увидели пару вопросов от людей, пытающихся сделать то же самое, что и мы - например, этот ответ и этот ответ .Мы прочитали блог Маркуса Зарры об импорте больших наборов данных в Core Data .Однако ни одно из решений, которые мы видели, не сработало для нас.Мы не хотим вручную читать и сохранять данные из добавочного хранилища в хранилище по умолчанию, так как считаем, что это будет очень медленно и подвержено ошибкам на телефоне.Есть ли более эффективный способ слияния?
Мы попытались решить эту проблему путем реализации миграции вручную следующим образом.Однако мы не смогли успешно добиться слияния.Мы не совсем понимаем решение, предложенное в ответах 1 и 2, упомянутых выше.В блоге Маркуса Зарры были рассмотрены некоторые проблемы, с которыми мы столкнулись в начале нашего проекта по импорту нашего большого набора данных в iOS.
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSMigrationManager *migrator = [[NSMigrationManager alloc] initWithSourceModel:__managedObjectModel destinationModel:__managedObjectModel];
if (![migrator migrateStoreFromURL:stateStoreURL
type:NSSQLiteStoreType
options:options
withMappingModel:nil
toDestinationURL:destinationStoreURL
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:&error])
{
NSLog(@"%@", [error userInfo]);
abort();
}
}
Кажется, что автор ответа 1 закончил читать свои данные из инкрементного хранилища исохранение в магазине по умолчанию.Возможно, мы неправильно поняли решение, предложенное в обеих статьях 1 и 2. Размер наших данных может помешать нам вручную читать и повторно вставлять наши инкрементные данные в хранилище по умолчанию.Мой вопрос: каков наиболее эффективный способ получить графы объектов из двух persistentStores (которые имеют одинаковую objectModel) для объединения в один persistentStore?
Автоматическая миграция работает очень хорошо, когда мы добавляем новые атрибуты сущностей в графы объектов или изменяем отношения.Существует ли простое решение для объединения похожих данных в одно и то же постоянное хранилище, которое будет достаточно гибким, чтобы его можно было остановить и возобновить, поскольку автоматическая миграция выполняется?