如何在应用程序中显示AlertView请求一次且仅一次种子iCloud'的iCloud使用寿命



我有一个问题快结束了。

我的工作信念/经验是,不止一次植入iCloud是个坏主意,如果用户能做错事,他迟早会做。

我想做的事:

A。当用户将应用程序首选项"启用iCloud"从"否"更改为"是"时,显示AlertView询问("是"或"否")用户是否希望使用现有的非iCloud数据植入云。

B。确保该应用程序在iCloud帐户上只对iCloud进行一次种子设定,第一次种子设定完成后不要显示AlertView。

我的方法:

  1. 根据苹果关于正确使用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])
    

    IMHO,这是我的问题的一个非常整洁的解决方案,但我不能完全完成。

    我的问题:

    如何响应第一个更新KVStoreItems:的通知?这是一个包含错误信息的通知。我说这个值是真的,但我从来没有把它设置为真。如何在NSUbiquitousKeyValueStore中设置密钥的默认值?

    我发现第一个通知是有原因的:NSUbiquitousKeyValueStoreInitialSyncChange当收到该注释时,bValue为YES。这是我的问题。就好像,iCloud/iOS假设任何新的BOOL都是TRUE。我需要这个值最初为NO,这样我就可以继续并遵循Apple Docs并设置将NSUserDefault设置为NO,然后在种子设定完成后,最终设置密钥的值:YES:@"iCloudSeeded"

    我发现我无法从苹果公司理解以下内容的含义:

    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,我相信我需要转到registerDefaults。

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

代码正在查找两个

    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=%dnNo 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;
            }
        }
    }

添加2014年9月3日很抱歉,我在使用BOOL时仍然遇到问题,我切换到了NSString,现在一切都很好。

确保在应用程序生命周期期间最多使用一次用于播种ICOUD的"合并"按钮的方法

  1. 在KV_STORE中使用NSString而不是BOOL。除学习外,无需添加观察者

  2. 在常数中。h:

    #define SEEDED_ICLOUD_MSG @"Have Seeded iCloud"
    #define ICLOUD_SEEDED_KEY @"iCloudSeeded"
    
  3. 在调用函数为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.
    
  4. 如果用户选择"是":则在合并完成后为"关键点"设置"值"。

    - (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];
            }
        }
    }
    
  5. 此后,在所有设备上,在所有时间内,代码

    NSUbiquitousKeyValueStore*kvStoretore=[NUbiquitous KeyValueStore defaultStore];NSString*消息=[kvStore字符串ForKey:ICLOUD_SSEEDED_KEY];

产生:msg==种子_ICLOUD_MESSAGE

最新更新