ios - 收到 SUbiquity Identity DidChangeNotification 后我应该做什么?

标签 ios objective-c core-data icloud uimanageddocument

Apple 文档说我们需要注册 NSUbiquityIdentityDidChangeNotification 并将当前 iCloud token 与之前存储在 NSUserDefaults 中的 token 进行比较,以检测用户是否从 文档和数据设置或切换到另一个 iCloud 帐户。

我使用标准的 UIManagedDocument 并以 iOS 7 为目标,因此回退存储由 CoreData 自动处理。

当我发现用户启用/禁用 iCloud 或切换到另一个帐户后,我不明白我应该做什么。我应该迁移持久存储吗?或者我应该在 NSPersistentStoreCoordinatorStoresDidChangeNotification 之后迁移它吗?或者我不应该迁移它,因为一切都由 CoreData 处理?

在多次观看 WWDC 2013 207 视频后,我认为这会由 Core Data 自动处理,但我发现如果我从 iCloud 支持开始,然后从文档和数据设置中关闭它,然后我插入新的 数据,然后我将 iCloud 切换回打开状态,我以两个不同的数据集结束。

我希望如果我发现用户禁用了 iCloud,那么本地数据库应该包含直到启用 iCloud 之前所做的最后一次更改,并且只有从这一点开始,所有内容都应该停止同步,直到再次启用 iCloud。

在 WWDC 2013 207 视频中,在 Melissa 演示中,我还注意到在 NSPersistentStoreCoordinatorStoresDidChangeNotification 之后对方法 [self migrateBack] 的调用,这让我感到困惑,因为幻灯片只显示我们应该在这里保存我们的上下文并刷新 UI,它们没有显示我们应该迁移任何东西:

**Account Changes Now**

NSPersistentStoreCoordinatorStoresWillChangeNotification
[NSManagedObjectContext save:]
[NSManagedObjectContext reset:] 

NSPersistentStoreCoordinatorStoresDidChangeNotification
[NSManagedObjectContext save:]

最佳答案

NSPersistentStoreCoordinatorStoresDidChangeNotification 通知与更改 iCloud 访问无关。

如果用户关闭 iCloud 访问或退出 iCloud,那么 Core Data 必须使用后备存储,这可能是空的!您将没有机会迁移任何内容。

但是,如果该应用有自己的“使用 iCloud”设置,那么您可以测试该更改,如果设置为“否”,则假设 iCloud 仍然可用,则将任何文档迁移到本地存储。

您可以在最新版本的 Pages 中看到预期的行为。如果您有 iCloud 文档,那么一旦您在设置应用程序中关闭 iCloud 文档和数据,您就会失去对 Pages 文档的所有访问权限。但是,如果您进入设置应用程序中的 Pages 设置并关闭使用 iCloud,然后切换回 Pages,系统将提示您保留在我的 iPhone 上、从我的 iPhone 中删除或继续使用 iCloud。这就是 Apple 希望您的应用运行的方式。

当应用程序进入前台时,我们会检查应用程序特定的 iCloud 设置,如果它们已更改,我们会采取必要的措施。

  1. 如果没有做出任何改变,那么我们继续运行
  2. 如果 iCloud 设置已更改,则:
    • 如果关闭,请询问用户该怎么做
    • 如果已打开,则共享 iCloud 中的所有文档

/*!该应用程序即将进入前台,因此请利用此机会检查用户是否更改了任何内容 设置。他们可能更改了 iCloud 帐户,登录或退出 iCloud,将文档和数据设置为关闭(与 如果他们退出 iCloud)或者他们可能更改了应用程序的特定设置。 如果设置已更改,请检查 iCloud 是否已关闭,并询问用户是否要将文件保存在本地。 否则只需将文件复制到 iCloud(不要再问用户,他们刚刚打开 iCloud,所以他们显然是认真的!)

@param application 应用程序 */

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    //LOG(@"applicationWillEnterForeground called");

    // Check if the app settings have been changed in the Settings Bundle (we use a Settings Bundle which
    // shows settings in the Devices Settings app, along with all the other device settings).
    [[NSUserDefaults standardUserDefaults] synchronize];
    NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
    bool userICloudChoice = [userDefaults boolForKey:_cloudPreferenceKey];


    // Now compare it with the current apps in memory setting to see if it has changed
    if (userICloudChoice  == useICloudStorage) {

        // No change so do nothing
        //LOG(@" iCloud choice has not changed");

    } else {

        // Setting has been changed so take action
        //LOG(@" iCloud choice has been changed!!");

        // iCloud option has been turned off
        if (!userICloudChoice) {

            //LOG(@" Ask user if they want to keep iCloud files locally ?");

            if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
                _cloudChangedAlert = [[UIAlertView alloc] initWithTitle:@"You're not using iCloud" message:@"What would you like to do with documents currently on this phone?" delegate:self cancelButtonTitle:@"Keep using iCloud" otherButtonTitles:@"Keep on My iPhone", @"Delete from My iPhone", nil];
            } else {
                _cloudChangedAlert = [[UIAlertView alloc] initWithTitle:@"You're not using iCloud" message:@"What would you like to do with documents currently on this phone?" delegate:self cancelButtonTitle:@"Keep using iCloud" otherButtonTitles:@"Keep on My iPad", @"Delete from My iPad", nil];

            }

            [_cloudChangedAlert show];
            // Handle the users response in the alert callback

        } else {

            // iCloud is turned on so just copy them across... including the one we may have open

            //LOG(@" iCloud turned on so copy any created files across");
            [[CloudManager sharedManager] setIsCloudEnabled:YES];  // This does all the work for us
            useICloudStorage = YES;

        }
    }

}

- (void)alertView:(UIAlertView*)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{

    if (alertView == _cloudChoiceAlert)
    {
        //LOG(@" _cloudChoiceAlert being processed");
        if (buttonIndex == 1) {
            //LOG(@" user selected iCloud files");
            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:_cloudPreferenceKey];
            [[NSUserDefaults standardUserDefaults] setValue:@"YES" forKey:_cloudPreferenceSet];
            useICloudStorage = YES;
            [[NSUserDefaults standardUserDefaults] synchronize];

            [[CloudManager sharedManager] setIsCloudEnabled:YES];
        }
        else {
            //LOG(@" user selected local files");
            [[NSUserDefaults standardUserDefaults] setBool:NO forKey:_cloudPreferenceKey];
            [[NSUserDefaults standardUserDefaults] setValue:@"YES" forKey:_cloudPreferenceSet];
            useICloudStorage = NO;
            [[NSUserDefaults standardUserDefaults] synchronize];

            [[CloudManager sharedManager] setIsCloudEnabled:NO];
        }
    }
    if (alertView == _cloudChangedAlert)
    {   //LOG(@" _cloudChangedAlert being processed");
        if (buttonIndex == 0) {
            //LOG(@" 'Keep using iCloud' selected");
            //LOG(@" turn Use iCloud back ON");
            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:_cloudPreferenceKey];
            [[NSUserDefaults standardUserDefaults] synchronize];
            useICloudStorage = YES;
        }
        else if (buttonIndex == 1) {
            //LOG(@" 'Keep on My iPhone' selected");
            //LOG(@" copy to local storage");
            useICloudStorage = NO;
            [[CloudManager sharedManager] setDeleteICloudFiles:NO];
            [[CloudManager sharedManager] setIsCloudEnabled:NO];

        }else if (buttonIndex == 2) {
            //LOG(@" 'Delete from My iPhone' selected");
            //LOG(@" delete copies from iPhone");
            useICloudStorage = NO;
            [[CloudManager sharedManager] setDeleteICloudFiles:YES];
            [[CloudManager sharedManager] setIsCloudEnabled:NO];
        }
    }

}

/*! Checks to see whether the user has previously selected the iCloud storage option, and if so then check
    whether the iCloud identity has changed (i.e. different iCloud account being used or logged out of iCloud).
    If the user has previously chosen to use iCloud and we're still signed in, setup the CloudManager 
    with cloud storage enabled.
    If no user choice is recorded, use a UIAlert to fetch the user's preference.

 */
- (void)checkUserICloudPreferenceAndSetupIfNecessary
{
    FLOG(@"checkUserICloudPreferenceAndSetupIfNecessary called");

    [[CloudManager sharedManager] setFileExtension:_fileExtension  andUbiquityID:_ubiquityContainerKey ];

    id currentToken = [[NSFileManager defaultManager] ubiquityIdentityToken];

    NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
    NSString* userICloudChoiceSet = [userDefaults stringForKey:_cloudPreferenceSet];

    bool userICloudChoice = [userDefaults boolForKey:_cloudPreferenceKey];

    userICloudChoice = [userDefaults boolForKey:_cloudPreferenceKey];

    //FLOG(@" User preference for %@ is %@", _cloudPreferenceKey, (userICloudChoice ? @"YES" : @"NO"));

    if (userICloudChoice) {

        //LOG(@" User selected iCloud");
        useICloudStorage = YES;
        [self checkUbiquitousTokenFromPreviousLaunch:currentToken];

    } else {

        //LOG(@" User disabled iCloud");
        useICloudStorage = NO;

    }

    // iCloud is active
    if (currentToken) {

        //LOG(@" iCloud is active");

        // If user has not yet set preference the prompt for them to select a preference
        if ([userICloudChoiceSet length] == 0) {

            _cloudChoiceAlert = [[UIAlertView alloc] initWithTitle:@"Choose Storage Option" message:@"Should documents be stored in iCloud or on just this device?" delegate:self cancelButtonTitle:@"Local only" otherButtonTitles:@"iCloud", nil];
            [_cloudChoiceAlert show];

        }
        else if (userICloudChoice ) {

            [[CloudManager sharedManager] setIsCloudEnabled:YES];

        }
    }
    else {
        //LOG(@" iCloud is not active");
        [[CloudManager sharedManager] setIsCloudEnabled:NO];
        useICloudStorage = NO;
        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:_cloudPreferenceKey];
        [[NSUserDefaults standardUserDefaults] synchronize];

        // Since the user is signed out of iCloud, reset the preference to not use iCloud, so if they sign in again we will prompt them to move data
        [userDefaults removeObjectForKey:_cloudPreferenceSet];
    }

    [self storeCurrentUbiquityToken:currentToken];
}

关于ios - 收到 SUbiquity Identity DidChangeNotification 后我应该做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20317662/

相关文章:

ios - 在 Swift 中实现 SWRevealViewController 的问题

ios - 如何以编程方式初始化 UINavigationController 的子类?

c++ - 指向 objc 类成员方法的函数指针,用于 C++?

objective-c - 调用viewDidLoad()中的方法。使用索引路径

iphone - CoreDataGeneratedAccessors - removeObject 是否删除对象?

ios - iOS 应用程序沙箱中的默认文件

ios - String的书写方向

ios - 带有 MagicalRecord 的核心数据不会保存到 iCloud

objective-c - 这有多糟糕?在 30 秒内分配了 3GB 总字节数

iphone - 将sqlite数据导入CoreData