Миграция существующих базовых данных в iCloud
У меня есть простое приложение, которое является UITableView
который заполняется пользователем, заполняющим некоторые UITextFields
по-другому. Эта информация сохраняется в CoreData
и UITableView
обновляется с помощью NSFetchedResultsController
,
Сейчас я внедряю синхронизацию iCloud в мою среду. Со ссылкой на ранее заданный вопрос: существующая база данных базовых данных не загружается в iCloud. При включении iCloud в моем приложении у меня все еще остаются проблемы, но это было слишком грязно, чтобы обновить этот вопрос моим новым кодом. Я имею в виду конкретно WWDC 2013 CoreData
Сессии, а также это. Потому что мое приложение только для iOS 7. Я довольно новичок в разработке iCloud и являюсь программистом среднего уровня.
У меня возникают большие трудности с переносом существующих данных в iCloud при обновлении с версии App Store (не iCloud) до версии для разработки (iCloud). Новые данные синхронизируются на отлично.
Я понимаю, что мне нужно по сути взять мой существующий магазин без iCloud и перенести его в iCloud, но это просто не работает для меня.
Вот код, иллюстрирующий то, над чем я работаю:
Обновить
Я прошел и подумал об этом и удалил код, который был излишним.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Planner.sqlite"];
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *url = [fm URLForUbiquityContainerIdentifier:nil];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (url)
{
NSLog(@"iCloud is enabled");
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
};
NSPersistentStore *localStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];
[_persistentStoreCoordinator migratePersistentStore:localStore toURL:[self iCloudURL] options:[self iCloudStoreOptions] withType:NSSQLiteStoreType error:&error];
}
else
{
NSLog(@"iCloud is not enabled");
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES
};
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self iCloudURL] options:options error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"Reload" object:self userInfo:nil];
});
return _persistentStoreCoordinator;
}
Я больше не вызываю метод migrateLocalStoreToiCloud, но он здесь для справки:
/*-(void)migrateLocalStoreToiCloud
{
//assuming you only have one store.
NSPersistentStore *store = [[_persistentStoreCoordinator persistentStores] firstObject];
NSPersistentStore *newStore = [_persistentStoreCoordinator migratePersistentStore:store
toURL:[self iCloudURL]
options:[self iCloudStoreOptions]
withType:NSSQLiteStoreType
error:nil];
[self reloadStore:newStore];
}
* /
storeURL
, storeOptions
, iCloudURL
а также iCloudStoreOptions
код является:
- (NSURL *)iCloudURL
{
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *url = [fm URLForUbiquityContainerIdentifier:nil];
if (url) {
NSLog(@"iCloud access at %@", url);
} else {
NSLog(@"No iCloud access");
}
return url;
}
-(NSURL *)storeURL{
return [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Planner.sqlite"];
}
-(NSDictionary *)storeOptions{
NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
return options;
}
-(NSDictionary *)iCloudStoreOptions{
NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:@"PlannerStore" forKey:NSPersistentStoreUbiquitousContentNameKey];
return options;
}
проблема
Когда я запускаю этот код в точности так, как он есть, я не отображается в консоли с помощью Local Storage : 1
а также 0
вообще, хотя данные есть.
Если я изменю persistentStoreCoordinator
где он сначала добавляет persistentStore для использования [self iCloudStoreOptions]
в качестве вариантов, Using Local Storage 1
а также 0
отображается, но данные не на устройстве.
Я следую приведенным здесь указаниям и попробовал несколько вариантов моего кода, в том числе не удаляя persistentStore в методе reloadStore, но я полностью застрял.
Я прочитал так много постов, но мне кажется, что я просто не могу найти кого-то, кто переносит данные из не-iCloud версии в версию iCloud, и с примерами, которые я нашел, кода нет.
Я посмотрел на это, и хотя это отличный кодовый набор, я скачал код и следовал этим рекомендациям, где он не удаляет любой persistentStore, но он все равно не будет работать для меня. Я не могу представить, что я пытаюсь достичь очень сложно. Мне просто нужно взять существующие данные не-iCloud и перенести их в iCloud.
Обновить
С прочтением руководства Apple: https://developer.apple.com/LIBRARY/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/UsingSQLiteStoragewithiCloud/UsingSQLiteStoragewithiCloud.html мой migrateLocaltoiCloud
метод в настоящее время неправильно с удалением persistentStore
и т. д., но я не могу понять, как это исправить. Если я позвоню это из persistentStoreCoordinator
Будет ли это как-то мешать DidChangeNotification
?
Я действительно застрял в этом, и я был бы признателен за любые указания в правильном направлении
1 ответ
Здесь я даю ответ на мой вопрос, потому что это понятнее, чем обновление вопроса, и после большой отладки у меня это работает, в некоторой степени.
С отладкой addPersistentStore
а также migratePersistentStore
Строки кода, я придумал:
NSPersistentStore *localStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];
NSLog(@"The localStore is %@", localStore);
NSPersistentStore *migratedStore = [_persistentStoreCoordinator migratePersistentStore:localStore toURL:[self iCloudURL] options:[self iCloudStoreOptions] withType:NSSQLiteStoreType error:&error];
NSLog(@"The migrationStore is %@", migratedStore);
The NSLog value of localStore is: The localStore is <NSSQLCore: 0x13451b100> (URL: file:///var/mobile/Applications/DDB71522-C61D-41FC-97C7-ED915D6C46A4/Documents/Planner.sqlite)
The NSLog value of migratedStore is: (null)
С отладкой я мог видеть, по сути, то же самое, что migrateStore всегда был нулевым.
Я немного изменил код:
NSPersistentStore *migratedStore = [_persistentStoreCoordinator migratePersistentStore:localStore toURL:storeURL options:[self iCloudStoreOptions] withType:NSSQLiteStoreType error:&error];
Чтобы URL был storeURL, и вдруг все заработало, где storeURL:
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Planner.sqlite"];
Мои выводы были:
The localStore is <NSSQLCore: 0x14ee09b50> (URL: file:///var/mobile/Applications/CC0F7DA0-251F-46D6-8E43-39D63062AED2/Documents/Planner.sqlite)
[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](771): CoreData: Ubiquity: mobile~5BD59259-7758-42FB-986F-DDD173F75ED3:EnStor
The migrationStore is <NSSQLCore: 0x157e260b0> (URL: file:///var/mobile/Applications/A08D183D-ECD4-4E72-BA64-D21727DE7A3E/Documents/CoreDataUbiquitySupport/mobile~CB6C3699-8BF1-47DB-9786-14BCE1CD570A/EnStor/771D2B0B-870A-428E-A9A8-5DAE1295AF53/store/Planner.sqlite)
Использование локального хранилища изменилось с 1 на 0, и мои данные из версии приложения из App Store продолжали оставаться там после перехода на новую версию. Это был вывод, когда я впервые запустил приложение после обновления.
Это отличные новости.
Однако каждый раз, когда я запускал приложение, данные продолжали мигрировать, и в результате я получал повторяющиеся результаты.
Проблема также заключается в том, что при добавлении нового устройства информация не выводится на новое устройство.
Я не совсем понимаю, почему использование storeURL в качестве URL-адреса для migratePersistentStore сработало?
Я также не хочу, чтобы каждое новое устройство в основном добавляло новое постоянное хранилище, если оно уже существует, и я не знаю, как мне обойти это, а также я не хочу, чтобы миграция происходила снова и снова. Это должно произойти только один раз.
Я добираюсь туда, но впереди еще много работы!