4

UITableView私は、ユーザーが別のビューに入力することによって入力される単純なアプリケーションを持っていUITextFieldsます。この情報は に保存されCoreDataUITableViewを使用して更新されNSFetchedResultsControllerます。

現在、私の環境に iCloud 同期を導入しています。以前に寄せられた質問:既存のコア データ データベースが iCloud にアップロードされていない場合、アプリで iCloud を有効にすると、まだ問題がありますが、新しいコードでその質問を更新するには面倒でした。私は特にWWDC 2013 CoreDataセッションとこれについて言及しています。私のアプリはiOS 7のみです。私は iCloud 開発の初心者で、中級プログラマーです。

App Store (iCloud 以外) バージョンから開発 (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のとおりです。iCloudURLiCloudStoreOptions

- (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;
}

問題

このコードをそのまま実行すると、コンソールに Using が表示されず、データは存在しますが、まったく表示されませLocal Storage : 10

オプションとしてpersistentStoreCoordinator使用するpersistentStoreを最初に追加する場所を変更すると、とが表示されますが、データはデバイス上にありません。[self iCloudStoreOptions]Using Local Storage 10

私はこちらのガイダンスに従っており、 reloadStore メソッドでpersistentStoreを削除しないなど、コードの複数のバリエーションを試しましたが、完全に行き詰まりました。

私は非常に多くの投稿を読みましたが、iCloud 以外のバージョンから iCloud バージョンにデータを移行している人を見つけることができないようで、私が見つけた例ではコードがありません。

私はこれを調べましたが、これは優れたコード セットですが、コードをダウンロードし、persistentStore を削除しないというガイドラインに従いましたが、それでもうまくいきません。私が達成しようとしていることが非常に複雑であるとは想像できません。既存の iCloud 以外のデータを取得して、iCloud に移行する必要があるだけです。

アップデート

Apple のガイドを読むと: https://developer.apple.com/LIBRARY/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/UsingSQLiteStoragewithiCloud/UsingSQLiteStoragewithiCloud.html#//apple_ref/doc/uid/TP40013491-CH3-SW2私のmigrateLocaltoiCloud方法は現在persistentStore、などの削除で間違っていますが、修正方法がわかりません。からこれを呼び出すpersistentStoreCoordinatorと、何らかの形で に干渉しDidChangeNotificationますか?

私は本当にこれにこだわっています。正しい方向へのガイダンスをいただければ幸いです

4

1 に答える 1

1

質問を更新するよりも明確であり、多くのデバッグを行った後、これがある程度機能するようになったため、ここで質問に対する回答を提供しています。

addPersistentStoremigratePersistentStore行のコードをデバッグすると、次のようになりました。

 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 が常に null であるという、本質的に同じことがわかりました。

コードを少し変更しました:

 NSPersistentStore *migratedStore = [_persistentStoreCoordinator migratePersistentStore:localStore toURL:storeURL options:[self iCloudStoreOptions] withType:NSSQLiteStoreType error:&error];

URL を 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)

Using Local Store は 1 から 0 になり、アプリの App Store バージョンからの私のデータは、新しいバージョンへの移行を通じて引き続きそこにありました。これは、アップグレード後に初めてアプリを実行したときの出力です。

これは素晴らしいニュースです。

その後アプリを実行するたびに、データが移行され続けたため、結果が重複してしまいました。

問題は、新しいデバイスを追加するときに、情報が新しいデバイスにプルダウンされないことです。

migratePersistentStore の URL として storeURL を使用する理由がよくわかりません。

また、新しいデバイスが既に存在する場合、基本的に新しい永続ストアを追加したくありません。これを回避する方法もわかりません。また、移行を何度も実行したくありません。発生するのは一度だけです。

私はそこに着いていますが、まだやるべきことがたくさんあります!

于 2014-05-16T13:29:18.623 に答える