为什么找不到 iCloud account/CKContainer

Why is iCloud account/CKContainer not being found

请在下面查看我更新的问题:

我正在使用 CloudKit 开发我的第一个应用程序。在查找交易之前,我正在尝试测试用户是否已连接到 iCloud。

这是我的代码(显示各种测试):

func isICloudContainerAvailable()->Bool {

        CKContainer.default().accountStatus { (accountStat, error) in
            if (accountStat == .available) {
                print("iCloud is available")
            }
            else {
                print("iCloud is not available")
            }
        }

        CKContainer.default().accountStatus { (accountStatus, error) in
            switch accountStatus {
            case .available:
                print("iCloud Available")
            case .noAccount:
                print("No iCloud account")
            case .restricted:
                print("iCloud restricted")
            case .couldNotDetermine:
                print("Unable to determine iCloud status")
            }
        }


        if FileManager.default.ubiquityIdentityToken != nil {
            //print("User logged in")
            return true
        }
        else {
            //print("User is not logged in")
            return false
        }
    }

这对我自己的帐户来说工作正常 -- 我可以按预期工作。但是,对于新用户(即 Apple Review 团队和我自己的测试用户),我得到

iCloud 不可用,并且 没有 iCloud 帐户

我确定有一个开放的 iCloud 帐户,因为新用户的 iCloud 邮件正在运行。

更新

我让测试用户注销并重新登录。她第一次启动该应用程序时,收到了 noCloud 消息。如果她重新启动应用程序,它就会工作。我可以在一些地方使用一些想法来查看。我已经使用我自己的计算机和一个新的测试帐户确认了这种行为。

根据文档,

The private database is available only when the value in the ubiquityIdentityToken property is not nil.

It also says

There are times when iCloud may not be available to your app, such as when the user disables the Documents & Data feature or signs out of iCloud.

文档和数据现在显然是设置中所谓的iCloud Drive

所以我想问问有问题的用户他们的 iCloud Drive 设置是否启用,打开它是否有任何不同。

我没有将此作为正确答案发布。但是,我从 Apple TSI 干预中了解到这是一个 Apple 错误。建议的解决方法——我仍在测试的方法如下:

func isICloudContainerAvailable()->Bool {
        print(#function)
        CKContainer.default().accountStatus { (accountStatus, error) in

            if accountStatus == .available {
                return
            }

            ///
            // Checking account availability
            // Silently return if everything goes well, or do a second check 200ms after the first failure
            //

            DispatchQueue.global().asyncAfter(deadline: .now() + 0.2) {

                    guard error != nil, accountStatus != CKAccountStatus.available else {return}

                        print("iCloud account is not available! Be sure you have signed in iCloud on this device!")
                    }
                }


        if FileManager.default.ubiquityIdentityToken != nil {
            //print("User logged in")
            return true
        }
        else {
            //print("User is not logged in")
            return false
        }

    }

它基本上做了以下事情..

  1. 检查容器是否可用。
  2. 如果没有,请等待 200 毫秒,然后重试。

这是一个 hack,200ms 是任意的。到目前为止,它似乎有效。