Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 收到NSUBiquityIdentityDidChange通知后,我应该做什么?_Ios_Objective C_Core Data_Icloud_Uimanageddocument - Fatal编程技术网

Ios 收到NSUBiquityIdentityDidChange通知后,我应该做什么?

Ios 收到NSUBiquityIdentityDidChange通知后,我应该做什么?,ios,objective-c,core-data,icloud,uimanageddocument,Ios,Objective C,Core Data,Icloud,Uimanageddocument,苹果文档称,我们需要注册NSUbiquityIdentityDidChangeNotification,并将当前的iCloud令牌与先前存储在NSUserDefaults中的令牌进行比较,以检测用户是否从文档和数据设置禁用iCloud或切换到另一个iCloud帐户 我使用标准的UIManagedDocument,并以iOS 7为目标,因此CoreData会自动处理回退存储 发现用户启用/禁用iCloud或切换到其他帐户后,我不明白该怎么办。我应该迁移持久存储吗?还是应该在发出NSPersiste

苹果文档称,我们需要注册
NSUbiquityIdentityDidChangeNotification
,并将当前的iCloud令牌与先前存储在
NSUserDefaults
中的令牌进行比较,以检测用户是否从文档和数据设置禁用iCloud或切换到另一个iCloud帐户

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

发现用户启用/禁用iCloud或切换到其他帐户后,我不明白该怎么办。我应该迁移持久存储吗?还是应该在发出
NSPersistentStoreCoordinatorsStoresIDChangeNotification
后迁移它?或者我应该永远不要迁移它,因为一切都是由CoreData处理的

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

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

在WWDC 2013 207视频中,在Melissa演示中,我还注意到在
NSPersistentStoreCoordinatorsStoresIDChangeNotification
之后调用了一个方法
[self migrateBack]
,这让我很困惑,因为幻灯片只显示我们应该在此处保存上下文并刷新UI,而没有显示我们应该迁移任何内容:

**Account Changes Now**

NSPersistentStoreCoordinatorStoresWillChangeNotification
[NSManagedObjectContext save:]
[NSManagedObjectContext reset:] 

NSPersistentStoreCoordinatorStoresDidChangeNotification
[NSManagedObjectContext save:]

nsPersistentStoreCoordinatorsStoresIDChangeNotification
通知与更改iCloud访问无关

如果用户关闭iCloud访问或注销iCloud,则核心数据必须使用回退存储,该存储可能为空!你将没有机会迁移任何东西

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


您可以在最新版本的页面中看到预期的行为。如果您有iCloud文档,则在设置应用程序中关闭iCloud文档和数据后,您将失去对页面文档的所有访问权限。但是,如果您转到设置应用程序中的页面设置并关闭使用iCloud,然后切换回页面,系统将提示您继续使用我的iPhone、从我的iPhone中删除或继续使用iCloud。这就是苹果希望你的应用程序能够工作的方式

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

  • 如果没有任何变化,我们将继续运行
  • 如果iCloud设置已更改,则:
    • 如果已关闭,请询问用户该怎么做
    • 如果已打开,则在iCloud中共享所有文档
  • /*!!应用程序即将进入前台,请利用此机会检查用户是否已更改任何内容 设置。他们可能更改了iCloud帐户,登录或注销了iCloud,将Documents&Data设置为off(与 如果他们注销了iCloud),或者他们可能更改了特定于应用程序的设置。 如果设置已更改,请检查iCloud是否已关闭,并询问用户是否希望在本地保存文件。 否则,只需将文件复制到iCloud(不要再问用户,他们刚刚打开了iCloud,所以他们显然是认真的!)

    @param应用程序应用程序 */


    我的应用程序没有自己的use iCloud设置,也永远不会有。用户将从设置应用程序启用/禁用iCloud。那么,在收到NSUBiquityIdentityDidChange通知后,我应该怎么做?询问他如何执行Pages示例中的操作,然后迁移?顺便说一句,感谢你这些天对我的支持!如果用户关闭iCloud,则无法迁移,因为您只能访问后备存储。用户必须重新打开iCloud才能访问数据,然后您必须提供其他选项-因此需要特定于应用程序的设置。请注意,特定于应用程序的设置仍在“设备设置”应用程序中设置,该设置在应用程序中不可用。您只需在应用程序中包含一个设置包,这将导致iOS设置应用程序创建特定于您的应用程序的条目。查看页面设置向下滚动第一页抱歉,我没有页面。如果我查看Document&Settigns应用程序,在iCloud->Documents&Data下,我已经看到我的应用程序的开/关开关。你指的是它吗?这是自动创建的,如果设备启用了iCloud,它会自动设置为打开,对我来说,这也意味着我不应该打扰用户,问他是否想在第一次运行应用程序时使用iCloud。我猜苹果提供的iCloud设计指南没有更新!不,这只是对全局设置的改进。网页是免费的,请下载。您将在与iCloud选项相同的页面上看到应用程序设置,只需进一步向下滚动即可。是的,他们的文档不是很新,他们拒绝了我的应用程序,直到我做了Pages做的事情。“但是如果你在设置应用程序中的Pages设置并关闭Use iCloud,然后切换回Pages,你会被提示继续使用我的iPhone,从我的iPhone中删除或继续使用iCloud。这就是苹果希望你的应用程序工作的方式。”好吧,我明白你的意思了,就像他们在车库乐队一样。你能发布一些代码来告诉我你对保留/删除/继续使用iCloud的反应吗?
    - (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];
    }