【问题标题】:Is it possible to intercept iCloud switching on/off in Settings -> iCloud -> Document & Data?是否可以在设置 -> iCloud -> 文档和数据中拦截 iCloud 打开/关闭?
【发布时间】:2013-12-15 13:52:16
【问题描述】:

如果用户在设置 -> iCloud -> 文档和数据下从开启到关闭iCloud支持是否可以拦截?

显然,当他这样做时,应用程序已经退出活动并进入后台。我的目标是 iOS7,我想与UIManagedDocument 保持同步,否则就像拥有两个不同的 UIDocument:一个支持 iCloud,并且在从打开切换到关闭之前创建了所有数据,另一个没有任何数据在里面。如果我在关闭 iCloud 支持时创建数据,然后再打开,我会得到与关闭支持时相同的数据库。

注意:我相信 nelico 的回答是对的。他写道:“如果您的应用程序正在运行并且用户更改通过设置应用程序启用或禁用文档和数据 iCloud 同步,您的应用程序将收到 SIGKILL 信号。”

当用户更改设置时,应用程序已经在后台并接收到 SIGKILL 信号。这是我不理解和不想要的。注册NSUbiquityIdentityDidChangeNotification 并不能解决这个问题。

【问题讨论】:

  • 因为您的数据库无论如何都在本地存储中。如果你想去掉 iCloud,你必须使用适当的存储选项。如果您在磁盘上缓存无处不在的密钥并在每次运行时匹配它,则可以这样做,如果不相同或为零,则进行迁移。

标签: ios objective-c core-data icloud uimanageddocument


【解决方案1】:

另一个更简洁的解决方案是侦听NSUbiquityIdentityDidChangeNotification 通知,当您收到该通知时,检查URLForUbiquityContainerIdentifier 如果它为空,他们要么退出,要么关闭“文档和数据”。您还应该跟踪当前的 ubiquity 令牌,以便您不仅可以知道他们是否注销,而且可以知道他们是否更改了 iCloud 帐户。这种情况的发生超出了人们的想象,因为 Apple Geniuses 喜欢在用户设备出现问题时创建一个新的 iCloud 帐户。

例如:

id <NSObject,NSCopying,NSCoding> _currentUbiquityIdentityToken;

...

_currentUbiquityIdentityToken = [[NSFileManager defaultManager] ubiquityIdentityToken];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (_iCloudAccountAvailabilityChanged:) name: NSUbiquityIdentityDidChangeNotification object: nil];

...

- (void)_iCloudAccountAvailabilityChanged:(NSNotification*)notif {
    if (![_currentUbiquityIdentityToken isEqual:[[NSFileManager defaultManager] ubiquityIdentityToken]]) {
        // Update the current token and rescan for documents.
        _currentUbiquityIdentityToken = [[NSFileManager defaultManager] ubiquityIdentityToken];
        // Do something about the change here...
    }
}

【讨论】:

  • 您的权利,我没有在您的条目中看到最后一行代码。我的回应更多是对接受的答案的回应。
  • 我相信 nelico 的回答是对的。他写道:“如果您的应用程序正在运行并且用户更改通过设置应用程序启用或禁用文档和数据 iCloud 同步,您的应用程序将收到 SIGKILL 信号。”当用户更改设置时,应用程序已经在前台并接收到 SIGKILL 信号。这是我不理解和不想要的。注册 NSUbiquityIdentityDidChangeNotification 并不能解决这个问题。
  • 那么NSUbiquityIdentityDidChangeNotification 的目的是什么,如果操作系统无论如何都会杀了你?如果发生这种情况,似乎是因为操作系统或应用程序本身存在错误。
  • 是的,这似乎是一个新的错误或功能,似乎只有在连接到 Xcode 时才会发生。用户无法使用前台应用程序更改设置应用程序中的设置,当他们在设置应用程序中时,应用程序必须切换到后台,当我的应用程序切换到后台时,我通常会取消注册通知,不记得确切原因的历史。
  • 我也认为这是一个错误。 IOS7 和 iCloud 非常复杂,因为没有来自 Apple 的示例代码并且更新到 2013 年 9 月的设计指南已经过时。例如,他们说在第一次运行应用程序时询问用户是否想使用 iCloud,但是当您在设备上安装应用程序时,如果用户已经使用 iCloud,它会自动打开,因此无需打扰他.如果他签字,那么我们可以拦截 NSUbiquityIdentityDidChangeNotification ......但是那该怎么办呢?我会问另一个问题。从 WWDC 207 开始,我们似乎应该进行某种迁移。
【解决方案2】:

通常您会将检查放在下面的方法中。这样,只要应用程序处于活动状态(包括首次启动),您就可以在将控制权返回给用户之前检查设置,而无需在后台进行轮询。对于 UIManagedDocument,您可能希望将商店迁移到仅本地副本并删除任何 iCloud 内容或相反,具体取决于用户输入。

顺便说一句,只需在上一个答案中包含检查,以测试全局 iCloud 设置是否已打开或关闭。我不这样做是因为只有在用户设置了应用特定设置时才需要更改应用行为。

/*! The app is about to enter foreground so use this opportunity to check if the user has changed any
    settings.  They may have changed the iCloud account, logged into or out of iCloud, set Documents & Data to off (same effect as
    if they logged out of iCloud) or they may have changed the app specific settings.
    If the settings have been changed then check if iCloud is being turned off and ask the user if they want to save the files locally.
    Otherwise just copy the files to iCloud (don't ask the user again, they've just turned iCloud on, so they obviously mean it!)

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

    // Check if the settings have changed
    [[NSUserDefaults standardUserDefaults] synchronize];
    NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
    bool userICloudChoice = [userDefaults boolForKey:_cloudPreferenceKey];

    // Check against the current in memory setting
    if (userICloudChoice  == useICloudStorage) {

        // The setting has not been changed so just ignore
        //LOG(@" iCloud choice has not changed");


    } else {

        // The setting has changed so do something
        //LOG(@" iCloud choice has been changed!!");

        // iCloud has been turned off so ask the user if they want to keep files locally
        if (!userICloudChoice) {
            //LOG(@" Ask user if  they want to keep iCloud files ?");

            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];

        } else {

            // iCloud has been turned on so just copy the files across, don't ask the user again...

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

        }
    }

}

哦,如果用户使用另一个 iCloud 帐户登录,还要注册此通知。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkUserICloudPreferenceAndSetupIfNecessary) name:NSUbiquityIdentityDidChangeNotification object:nil];

【讨论】:

  • 请注意,UIUserInterfaceIdiomPhone 并不意味着该设备是 iPhone。它也可以是 iPod Touch。
【解决方案3】:

无法拦截更改,但您可以通过编程方式检查它们是否启用了 iCloud:

NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *ubiquityContainerURL = [fileManager URLForUbiquityContainerIdentifier:nil];
if (!ubiquityContainerURL) {
    // iCloud is not enabled
}

当您的应用进入后台时,您可以定期轮询它并让您的应用响应任何状态变化。

编辑:如果您的应用正在运行并且用户通过设置应用更改启用或禁用文档和数据 iCloud 同步,您的应用将收到 SIGKILL 信号。但是,操作系统可能会出于多种原因终止您的应用程序,因此捕获 SIGKILL 不是拦截 iCloud 同步设置更改的可靠方法。你最好还是定期轮询。

【讨论】:

  • 不完全准确...您可以通过NSUbiquityIdentityDidChangeNotification 通知了解帐户是否已更改或已注销 - 请参阅我的答案。
猜你喜欢
  • 2014-03-20
  • 1970-01-01
  • 2013-05-25
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
  • 2017-03-12
  • 2014-12-05
相关资源
最近更新 更多