NSPersistentStoreCoordinatorStoresDidChangeNotification 通知与更改 iCloud 访问权限无关。
如果用户关闭 iCloud 访问或从 iCloud 注销,那么 Core Data 必须使用后备存储,这可能是空的!您将没有机会迁移任何内容。
但是,如果应用程序有自己的“使用 iCloud”设置,那么您可以测试该更改,如果设置为“否”,则假设 iCloud 仍然可用,则将任何文档迁移到本地存储。
您可以在最新版本的 Pages 中看到预期的行为。如果您有 iCloud 文档,那么一旦您在设置应用程序中关闭 iCloud 文档和数据,您就会失去对 Pages 文档的所有访问权限。但是,如果您进入设置应用程序中的 Pages 设置并关闭使用 iCloud,然后切换回 Pages,您将被提示在我的 iPhone 上保留、从我的 iPhone 中删除或继续使用 iCloud。这就是 Apple 期望您的应用运行的方式。
当应用程序进入前台时,我们会检查应用程序特定的 iCloud 设置,如果它们发生了变化,我们会采取必要的措施。
- 如果没有进行任何更改,那么我们将继续运行
- 如果 iCloud 设置已更改,则:
- 如果关闭,请询问用户该怎么做
- 如果已开启,则共享 iCloud 中的所有文档
/*!该应用程序即将进入前台,因此请借此机会检查用户是否更改了任何内容
设置。他们可能更改了 iCloud 帐户,登录或退出 iCloud,将 Documents & Data 设置为关闭(效果与
如果他们退出了 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];
}