Миграция существующих базовых данных в 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 сработало?

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

Я добираюсь туда, но впереди еще много работы!

Другие вопросы по тегам