CKContainer.discoverAllIdentities 总是失败

Posted

技术标签:

【中文标题】CKContainer.discoverAllIdentities 总是失败【英文标题】:CKContainer.discoverAllIdentities always fails 【发布时间】: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 提交错误报告。 【参考方案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 时得到的结果非常相似。

以上是关于CKContainer.discoverAllIdentities 总是失败的主要内容,如果未能解决你的问题,请参考以下文章