0

最後に一つ質問があります。

私は、iCloud を複数回シードすることは悪い考えであり、ユーザーが間違ったことをする可能性がある場合、遅かれ早かれそうするだろうという信念/経験に基づいて取り組んでいます。

私がしたいこと:

A. ユーザーがアプリ設定の「iCloud を有効にする」を NO から YES に変更した場合、AlertView を表示して、ユーザーが既存の非 iCloud データをクラウドにシードするかどうか (Yes または No) を尋ねます。

B. アプリが iCloud アカウントで一度だけ iCloud をシードすることを確認し、最初のシードが完了したら AlertView を表示しないようにします。

私の方法:

  1. NSUbiquitousKeyValueStore の適切な使用に関する Apple のドキュメントに従って、- (void)application: dFLWOptions: で次のメソッドを使用しています。

    - (void)updateKVStoreItems:(NSNotification*)notification {
        // Get the list of keys that changed.
        NSDictionary* userInfo = [notification userInfo];
        NSNumber* reasonForChange = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey];
        NSInteger reason = -1;
            // If a reason could not be determined, do not update anything.
        if (!reasonForChange)
            return;
            // Update only for changes from the server.
        reason = [reasonForChange integerValue];
        if ((reason == NSUbiquitousKeyValueStoreServerChange) ||
             (reason == NSUbiquitousKeyValueStoreInitialSyncChange)) { // 0 || 1
                // If something is changing externally, get the changes
                // and update the corresponding keys locally.
            NSArray* changedKeys = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey];
            NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];
            NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
                // This loop assumes you are using the same key names in both
                // the user defaults database and the iCloud key-value store
            for (NSString* key in changedKeys) {//Only one key: @"iCloudSeeded" a BOOL
                BOOL bValue = [store boolForKey:key];
                id value = [store objectForKey:@"iCloudSeeded"];
                [userDefaults setObject:value forKey:key];
            }
        }
    

    }

  2. アプリケーションの上部近くに次のコードを含めます: dFLWO:

    NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                    selector:@selector(updateKVStoreItems:)
                                            name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification
                                                                 object:store]; // add appDelegate as observer
    
  3. iCloud ストアをロードした後、シードが行われていない場合にのみ、iCloud 以外のデータでシードします。

    - (BOOL)loadiCloudStore {
        if (_iCloudStore) {return YES;} // Don’t load iCloud store if it’s already loaded
    
        NSDictionary *options =
        @{
        NSMigratePersistentStoresAutomaticallyOption:@YES
        ,NSInferMappingModelAutomaticallyOption:@YES
        ,NSPersistentStoreUbiquitousContentNameKey:@"MainStore"
        };
        NSError *error=nil;
        _iCloudStore = [_coordinator addPersistentStoreWithType:NSSQLiteStoreType
                                configuration:nil URL:[self iCloudStoreURL] options:options error:&error];
        if (_iCloudStore) {
            NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];
            BOOL iCloudSeeded =
                [store boolForKey:@"iCloudSeeded"];//If the key was not found, this method returns NO.
            if(!iCloudSeeded) // CONTROL IS HERE
                [self confirmMergeWithiCloud]; // Accept one USER confirmation for seeding in AlertView ONCE world wide
            return YES; // iCloud store loaded.
        }
        NSLog(@"** FAILED to configure the iCloud Store : %@ **", error);
        return NO;
    }
    
  4. 播種が完了したら、次の手順を実行して、播種の繰り返しを防ぎます。

    if (alertView == self.seedAlertView) {
            if (buttonIndex == alertView.firstOtherButtonIndex) {
                [self seediCloud];
                NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];
                [store setBool:YES  forKey:@"iCloudSeeded"]; // NEVER AGAIN 
                    //[store synchronize];
            }
        }
    }
    
  5. 上記のプロセスを実行する前に、以下を使用して iCloud を完全にリセットしてください。

    [NSPersistentStoreCoordinator
          removeUbiquitousContentAndPersistentStoreAtURL:[_iCloudStore URL]
          options:options
          error:&error])
    

    これは私の問題、私見に対する非常にきちんとした解決策ですが、完全にはやり遂げることができません。

    私の質問:

    上記の updateKVStoreItems: への最初の通知にどのように対応すればよいですか? 悪い情報のお知らせです。値はTRUEだと言いますが、TRUEに設定したことはありません。NSUbiquitousKeyValueStore でキーのデフォルト値を設定するにはどうすればよいですか?

    最初の通知が理由であることがわかりました: NSUbiquitousKeyValueStoreInitialSyncChange そのメモが来ると、bValue は YES です。これは私の問題です。あたかも、iCloud/iOS が新しい BOOL を TRUE であると想定しているかのようです。Apple Docs に従って NSUserDefault を NO に設定できるように、最初はこの値を NO にする必要があります。その後、シード処理が完了したら、最終的に値を設定します: キーの YES:@"iCloudSeeded"

    Apple からの次のメッセージの意味を理解できないことがわかりました。

    NSUbiquitousKeyValueStoreInitialSyncChange
    Your attempt to write to key-value storage was discarded because an initial download from iCloud has not yet happened. 
    That is, before you can first write key-value data, the system must ensure that your app’s local, on-disk cache matches the truth in iCloud.
    Initial downloads happen the first time a device is connected to an iCloud account, and when a user switches their primary iCloud account.
    

    オンラインで見つけた以下の2番の意味がよくわかりません。

     NSUbiquitousKeyValueStoreInitialSyncChange – slightly more complicated, only happens under these circumstances:
    1. You start the app and call synchronize
    2. Before iOS has chance to pull down the latest values from iCloud you make some changes.
    3. iOS gets the changes from iCloud.
    

    この問題が NSUbiquitousKeyValueStore ではなく NSUserDefaults にある場合は、registerDefaults に行く必要があると思います。

    もうすぐそこです。どうすればいいですか。読んでくれてありがとう、マーク

4

1 に答える 1