В нашем разрабатываемом приложении мы используем Core Data с хранилищем sqlite для хранения наших данных. Объектная модель для нашего приложения сложна. Кроме того, общий объем данных, обслуживаемых нашим приложением, слишком велик, чтобы вписаться в комплект приложений для iOS (iPhone/iPad/iPod Touch). Из-за того, что наши пользователи, как правило, заинтересованы только в подмножестве данных, мы разделили наши данные таким образом, что приложение поставляется с подмножеством (хотя и около 100 МБ) объектов данных в приложение. Наши пользователи имеют возможность загружать дополнительные данные (размером от 5 МБ до 100 МБ) с нашего сервера после того, как они платят за дополнительное содержимое через покупки iTunes в приложении. Инкрементные файлы данных (существующие в хранилищах хранилища sqlite) используют ту же версию xcdatamodel, что и данные, поставляемые вместе с пакетом; в объектной модели нулевые изменения. Инкрементные файлы данных загружаются с нашего сервера в виде файлов с поддержкой gzipped sqlite. Мы не хотим раздувать наш пакет приложений, отправляя инкрементное содержимое с помощью приложения. Кроме того, мы не хотим полагаться на запросы через webservice (из-за сложной модели данных). Мы протестировали загрузку инкрементных данных sqlite с нашего сервера. Мы смогли добавить загруженное хранилище данных в общедоступный persistentStoreCoordinator приложения. Что такое эффективный способ слияния двух постоянных хранилищ данных iOS Core?
{
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.
- Некоторые объекты дублируются. В нашей модели данных имеется много объектов с данными только для чтения; они дублируются, когда мы добавляем второй постоянный сервер в постоянныйStoreCoordinator .
В идеале мы хотели бы, чтобы Core Data объединил графические объекты из двух постоянных хранилищ в один (нет общих отношений между данными из двух хранилищ во время загрузки данных). Кроме того, мы хотели бы удалить дубликаты объектов. Поиск в Интернете, мы видели пару вопросов от людей, пытающихся сделать то же самое, что мы делаем - например, this answer и this answer. Мы читали Marcus Zarra's blog on importing large data sets in Core Data. Однако ни одно из решений, которые мы видели, не сработало для нас. Мы не хотим вручную считывать и сохранять данные из инкрементного хранилища в хранилище по умолчанию, поскольку мы считаем, что это будет очень медленным и подверженным ошибкам на телефоне. Существует ли более эффективный способ слияния?
Мы попытались решить проблему, выполнив ручную миграцию следующим образом. Однако нам не удалось успешно добиться слияния. Мы не совсем поняли решение, предложенное в ответах 1 и 2, упомянутых выше. В блоге Marcus Zarra были затронуты некоторые проблемы, которые мы имели в начале нашего проекта, импортируя наш большой набор данных в 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. Размер наших данных может помешать нам вручную считывать и повторно вставлять наши инкрементные данные в хранилище по умолчанию. Мой вопрос: какой самый эффективный способ получить графы объектов из двух постоянных хранилищ (имеющих один и тот же объектModel), чтобы объединиться в один постоянный хранилище?
Автоматическая миграция работает очень хорошо, когда мы добавляем новые атрибуты сущностей в графы объектов или изменяем отношения. Есть ли простое решение для слияния подобных данных с одним и тем же постоянным хранилищем, которое будет достаточно устойчивым, чтобы останавливаться и возобновляться - как автоматическая миграция выполняется?
Где Маркус Зарра, когда он мне нужен? Я сделал некоторый прогресс, используя метод [NSPersistentStore migratePersistentStore: toURL: options: withType: error]. Мне просто нужно еще немного очистить код, чтобы добраться туда, где я должен быть. – Sunny
Я борюсь с тем же. Можете ли вы опубликовать то, что вы придумали? Я потерялся. – damon
Сделано! Дайте мне знать, как это получается для вас. – Sunny