【问题标题】:CKContainer.discoverAllIdentities always failsCKContainer.discoverAllIdentities 总是失败
【发布时间】:2017-08-16 00:23:09
【问题描述】:

CKContainer.discoverAllIdentities 请求在我的 CloudKit 应用程序中总是失败。它在几天内不断失败。

失败的代码的简化版本(导致相同的错误)是:

private func getContacts(completion: (([CKUserIdentity]?) -> Void)?) {
    container.status(forApplicationPermission: .userDiscoverability) { [weak self] status, error in
        if let error = error {
            print(error)
        }

        switch status {
        case .granted:
            self?.discover(completion: completion)
        default:
            print("status not granted")
        }
    }
}

private func discover(completion: (([CKUserIdentity]?) -> Void)?) {
    let op = CKDiscoverAllUserIdentitiesOperation()
    op.qualityOfService = .userInitiated
    op.discoverAllUserIdentitiesCompletionBlock = { error in
        if let error = error {
            print(error)
        }
    }
    op.userIdentityDiscoveredBlock = { identity in
        print(identity)
    }
    op.start()
}

这会导致将错误传递给op.discoverAllUserIdentitiesCompletionBlock。日志中的错误描述为:

<CKError 0x1c4a51a60: "Server Rejected Request" (15/2000); server message = "Internal server error"; uuid = F67453B9-712D-4E5E-9335-929123E3C978; container ID = "iCloud.com.huntermaximillionmonk.topdraw">

以前,此操作可以工作,但仅适用于某些 iCloud 用户。现在它不适用于我的两个测试用户。

【问题讨论】:

  • 遇到同样的问题,如果您设法解决了,请告诉我。
  • 还是有问题。我发现它只发生在有很多联系人的设备上。尝试在联系人很少 (
  • 那好点试试看!
  • 我刚刚尝试了 400 个联系人,操作没有失败。似乎还有其他问题。我能够找到发现的联系人。
  • 此错误是 iOS 11 中的错误。同样的代码在 iOS 10 下也可以正常工作。我强烈建议任何受 iOS 11 中此问题影响的人都应该向 Apple 提交错误报告。

标签: swift cloudkit


【解决方案1】:

问题:

这是 iOS 中的问题11.0

根据我的测试:

这在设备(不是模拟器)上的Xcode 9.2 / iOS 11.2.1 中正常工作

重置模拟器第一次可以工作,后来就不行了,但是在设备上又可以重复了。

代码:

let queue = OperationQueue()

func requestPermissions(for permissions: CKApplicationPermissions,
                        completionHandler: @escaping (CKApplicationPermissionStatus, Error?) -> ()) {
    
    CKContainer.default().requestApplicationPermission(permissions) { status, error in
        
        if let error = error {
            
            print("Error for requesting \(permissions) - \(error)")
        }
        
        let statusMessage : String
        
        switch status {
            
        case .granted:
            statusMessage = "Granted"
        case .denied:
            statusMessage = "Denied"
        case .couldNotComplete:
            statusMessage = "Could not complete"
        case .initialState:
            statusMessage = "Initial state"
        }
        
        print("Permission - \(statusMessage)")
        
        completionHandler(status, error)
    }
}


private func discoverAllUsers() {
    
    let operation = CKDiscoverAllUserIdentitiesOperation()
    
    operation.userIdentityDiscoveredBlock = { userIdentity in
        
        print("userIdentity = \(userIdentity)")
    }
    
    operation.discoverAllUserIdentitiesCompletionBlock = { error in
        
        if let error = error {
            
            print("Discover all users Error: \(error) ")
        }
        else {
            print("Discover all users completed successfully")
        }
    }
    
    queue.addOperation(operation)
}

【讨论】:

  • 有趣,我在 11.2.1 上仍然遇到此错误。您有可以发布的要点供我测试吗?
  • 重置模拟器后,第一次运行,后续运行不运行。在运行 iOS 11.2.1 的设备上运行一致。我已经更新了我的答案。
【解决方案2】:

编辑:

苹果在这个答案发布后的第二天就解决了这个问题,巧合?!我不这么认为:)


这实际上不是问题的答案,而是帮助我克服此错误的修复程序。这将要求您更改您的应用程序 UI 交互并将 ContactsUI 框架添加到您的项目中,而且您的用户将负责选择与 iCloud 相关的电子邮件的联系人。

好消息是discoverUserIdentity 方法仍然有效。因此,您可以使用它从手动选择的联系人中获取CKUserIdentity

func addContact(_ contact:CNContact) {

     var lookUpEmails = [CKUserIdentityLookupInfo]()
     for email in contact.emailAddresses {
         lookUpEmails.append(CKUserIdentityLookupInfo(emailAddress: (email.value as String)))
     }

     let checkUserOperation = CKDiscoverUserIdentitiesOperation()
        
     checkUserOperation.userIdentityLookupInfos = lookUpEmails
        
     checkUserOperation.userIdentityDiscoveredBlock = { [unowned self] (identity, info) -> Void in
         if identity.hasiCloudAccount {
             if let recordID = identity.userRecordID {
                  //do something with discovered user
             }
             checkUserOperation.cancel()
         }
     }
     checkUserOperation.queuePriority = Operation.QueuePriority.high
     CKContainer.default().add(checkUserOperation)
}

这听起来可能没用,但就我而言,它帮助我解决了Server Rejected Request" (15/2000) 错误,修复了我的应用程序的一个功能,并以比我想象的更少的努力继续使用其他功能相关的代码。

我希望有人会觉得这很有帮助。

【讨论】:

  • 这很好!不幸的是,正如您所说,它不能解决“我的哪些朋友在使用这个应用程序”的问题。
  • @HunterMaximillionMonk 是的,这是真的。但是,你知道你可以尝试什么吗?您可以尝试询问用户联系人,然后通过电子邮件请求联系人列表并检查他们的用户身份。这些身份仅适用于您的应用程序的用户。 (据我了解)。
  • 在 iOS 11.2 (Xcode 9.2) 中,可发现性对我来说似乎没问题。看起来现在已经修复了。我在 iOS 11.0 早些时候遇到过这个问题
  • @user1046037 是的,现在看起来一切正常。
  • 最好更新答案并声明它现在已修复而无需解决方法,以便对其他人有所帮助。谢谢
【解决方案3】:

这只是另一个可能有助于整体情况的数据点。当我在运行名为 discoverAllIdentitiesWithCompletionHandler 的测试应用程序时使用自己的 iCloud AppleID(具有数百个联系人)时,我仍然在 11.2.5 上看到此错误。我会得到可怕的 CKError 0x1c0051730:“服务器拒绝请求”(15/2000); server message = "内部服务器错误"。 当我切换到在我女儿的 iOS11.2.5 设备(只有少数联系人)上运行完全相同的代码时,代码运行良好。 让我相信当与 iOS11 有很多联系时,会有一些速率限制。 (P.S. 在 iOS10 上运行完全没有错误)

【讨论】:

  • 这与我在个人 iPhone 上测试联系人上传与测试 iPad 时得到的结果非常相似。
猜你喜欢
  • 2016-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多