Apple文档说我们需要注册NSUbiquityIdentityDidChangeNotification
并将当前的iCloud令牌与先前存储在NSUserDefaults
中的令牌进行比较,以检测用户是否从 Documents& ;数据设置 或切换到另一个iCloud帐户。
我使用标准UIManagedDocument
并且我定位iOS 7,因此后备存储由CoreData自动处理。
我发现用户启用/禁用iCloud或切换到其他帐户后,我不明白应该怎么做。我应该迁移持久性商店吗?或者我应该在NSPersistentStoreCoordinatorStoresDidChangeNotification
后迁移它吗?或者我应该永远不会迁移它,因为所有内容都由CoreData处理?
多次观看WWDC 2013 207视频后,我认为这将由Core Data自动处理,但我发现如果我从iCloud支持开始,然后我将其从Document&数据设置,我插入新的 数据,然后我切换回iCloud,我结束了两个不同的数据集。
我希望如果我发现用户禁用了iCloud,那么本地数据库应该包含最后一次更改,直到启用iCloud,并且只有从这一点开始,一切都应该停止同步,直到iCloud再次启用。
在WWDC 2013 207视频中,在Melissa演示中,我还注意到在[self migrateBack]
之后调用方法NSPersistentStoreCoordinatorStoresDidChangeNotification
,这让我感到困惑,因为幻灯片只是显示我们应该在这里保存我们的上下文并刷新用户界面,他们没有表明我们应该迁移任何东西:
**Account Changes Now**
NSPersistentStoreCoordinatorStoresWillChangeNotification
[NSManagedObjectContext save:]
[NSManagedObjectContext reset:]
NSPersistentStoreCoordinatorStoresDidChangeNotification
[NSManagedObjectContext save:]
答案 0 :(得分:4)
NSPersistentStoreCoordinatorStoresDidChangeNotification
通知与更改iCloud访问无关。
如果用户关闭iCloud访问权限或退出iCloud,则Core Data必须使用后备存储,这可能是空的!你不会有机会迁移任何东西。
但是,如果应用程序有自己的使用iCloud设置,那么您可以测试该更改,如果设置为NO,则假设iCloud仍然可用,则将任何文档迁移到本地存储。
您可以在最新版本的Pages中查看预期的行为。如果您有iCloud文档,那么只要您关闭iCloud Documents&设置应用程序中的数据您放弃了对Pages文档的所有访问权限。但是,如果您转到设置应用程序中的页面设置并关闭使用iCloud,然后切换回页面,系统将提示您保留在我的iPhone上,从我的iPhone删除或继续使用iCloud。这就是Apple希望你的应用运行的方式。
当应用程序进入前台时,我们会检查应用程序特定的iCloud设置,如果它们已更改,我们会采取必要的措施。
/ *!该应用程序即将进入前台,因此请利用此机会检查用户是否已更改任何内容 设置。他们可能已经更改了iCloud帐户,登录或退出iCloud,设置了Documents&关闭数据(效果相同) 如果他们退出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];
}