如何在应用程序的iCloud生命周期中显示一个AlertView请求权限,只能在iCloud中播种一次?

时间:2014-09-01 04:05:53

标签: ios nsubiquitouskeyvaluestore

我最后有一个问题。

我的信念/经验表明,不止一次播种iCloud是一个坏主意,如果用户可以做错事,他可能迟早会。

我想做什么:

一个。当用户更改应用程序首选项时#34;启用iCloud"从NO到YES,如果用户希望使用现有的非iCloud数据播种云,则显示AlertView询问(是或否)。

B中。确保应用程序仅在iCloud帐户上播放一次iCloud,并在第一次完成播种后禁止放置AlertView。

我的方法:

  1. 关于Apple正确使用NSUbiquitousKeyValueStore的文档后,我在 - (void)应用程序中使用以下方法: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 Store后,如果从未进行过播种,则仅使用非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都是正确的。 我最初需要这个值为NO,以便我可以继续并遵循Apple Docs并设置 NSUserDefault为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.
    

    如果这个问题出在NSUserDefaults而不是NSUbiquitousKeyValueStore,我相信我需要去注册默认。

    我快到了, 请问我该怎么做! 感谢阅读,Mark

1 个答案:

答案 0 :(得分:0)

代码正在寻找

    A. NSUbiquitousKeyValueStoreInitialSyncChange and 
    B. NSUbiquitousKeyValueStoreServerChange

我无法弄清楚如何处理通知。我知道看到我也不需要做任何事情。我的应用程序只需要读写,以解决我在问题标题中列出的问题。

该应用获取当前值:

    NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];
    BOOL iCloudSeeded = [store boolForKey:@"iCloudSeeded"];

该应用程序使用以下命令设置NSUbiquitousKeyValueStore中的值:

    NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];
    [store setBool:YES  forKey:@"iCloudSeeded"];

我相信我说的是正确的:写作是在记忆中完成的。此后不久,系统将数据放入磁盘。  从那里开始,它被带入iCloud并在同一个iCloud帐户上运行相同应用程序的其他设备上可用。在我描述的应用程序中,不需要添加观察者,并且  没有别的事情需要做。这可能是NSUbiquitousKeyValueStore的“不寻常”使用。

如果您来到这里寻找更“常用”的用法,请说当用户在文本视图中输入内容时  出现在运行相同应用程序的其他设备的视图上,查看我遇到的简单演示:

    https://github.com/cgreening/CMGCloudSyncTest

更好的功能(仅监控)通知处理程序如下:

    - (void)updateKVStoreItems:(NSNotification*)notification {
        NSNumber *reason = notification.userInfo[NSUbiquitousKeyValueStoreChangeReasonKey];
        if(!reason) return;
            // get the reason code
        NSInteger reasonCode = [notification.userInfo[NSUbiquitousKeyValueStoreChangeReasonKey] intValue];
        BOOL bValue;
        NSUbiquitousKeyValueStore *store;

        switch(reasonCode) {
            case NSUbiquitousKeyValueStoreServerChange:{ // code 0, monitoring only
                store = [NSUbiquitousKeyValueStore defaultStore];
                bValue = [store boolForKey:@"iCloudSeeded"];
                id value = [store objectForKey:@"iCloudSeeded"];
                DLog(@"New value for iCloudSeeded=%d\nNo Action need be take.",bValue);
                    // For monitoring set in UserDefaults
                [[NSUserDefaults standardUserDefaults] setObject:value forKey:@"iCloudSeeded"];
                break;
            }
            case NSUbiquitousKeyValueStoreAccountChange: {// ignore, log
                NSLog(@"NSUbiquitousKeyValueStoreAccountChange");
                break;
            }
            case NSUbiquitousKeyValueStoreInitialSyncChange:{ // ignore, log
                NSLog(@"NSUbiquitousKeyValueStoreInitialSyncChange");
                break;
            }
            case NSUbiquitousKeyValueStoreQuotaViolationChange:{ // ignore, log
                NSLog(@"Run out of space!");
                break;
            }
        }
    }

添加9/3/14 很抱歉,但是我仍然无法使用BOOL,我现在切换到NSString 一切都很好。

确保在APP生命周期内最大限度地使用“合并”用于种植ICO的按钮的方法

  1. 在KV_STORE中使用NSString而不是BOOL。除学习

  2. 外,无需添加观察者
  3. 在Constants.h中:

    #define SEEDED_ICLOUD_MSG @"Have Seeded iCloud"
    #define ICLOUD_SEEDED_KEY @"iCloudSeeded"
    
  4. 在调用函数以使用非iCloud数据播种iCloud之前:

    NSUbiquitousKeyValueStore* kvStore = [NSUbiquitousKeyValueStore defaultStore];
    NSString* strMergeDataWithiCloudDone =
                [kvStore stringForKey:ICLOUD_SEEDED_KEY];
    NSComparisonResult *result = [strMergeDataWithiCloudDone compare:SEEDED_ICLOUD_MSG];
    if(result != NSOrderedSame)
        //put up UIAlert asking user if seeding is desired.
    
  5. 如果用户选择YES:在合并完成后设置Key的值。

    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
        if (alertView == self.seedAlertView) {
            if (buttonIndex == alertView.firstOtherButtonIndex) {
                [self seediCloudwithNoniCloudData];
                NSUbiquitousKeyValueStore* kvStoretore = [NSUbiquitousKeyValueStore defaultStore];
                [store setObject:SEEDED_ICLOUD_MSG forKey:ICLOUD_SEEDED_KEY];
            }
        }
    }
    
  6. 此后在所有设备上,所有时间,代码

    NSUbiquitousKeyValueStore * kvStoretore = [NSUbiquitousKeyValueStore defaultStore]; NSString * msg =      [kvStore stringForKey:ICLOUD_SEEDED_KEY];

  7. 生成:msg == SEEDED_ICLOUD_MESSAGE