为啥 CloudKit 不允许我将任何记录保存到默认容器的公共数据库中?

Posted

技术标签:

【中文标题】为啥 CloudKit 不允许我将任何记录保存到默认容器的公共数据库中?【英文标题】:Why is CloudKit not allowing me to save any records to my default container's public database?为什么 CloudKit 不允许我将任何记录保存到默认容器的公共数据库中? 【发布时间】:2017-09-11 05:41:16 【问题描述】:

我有一个 CKRecords 数组,我第一次尝试将它们保存到默认 Container 的公共数据库中。我创建了一个 CKModifyRecordsOperation 并尝试将该操作添加到公共数据库。它不成功,但我没有收到任何错误消息。所以我尝试将每个方法单独添加到数据库中,没有任何 CKOperation ......同样不成功,也没有错误消息。可以肯定的是,我检查了我的 CloudKit 仪表板;那里什么都没有。

以下是有问题的方法。它连接到一个简单的 IBAction,用于 NSWindow 中的按钮。您可以忽略我从模型数据创建 CKRecords 的嵌套循环。他们似乎按预期工作。我的错误检查代码位于 CKModifyRecordsOperation 的完成块内。具体来说, modifyRecordsCompletionBlock 正在打印:“Saved 0 records into CloudKit。”

    @IBAction func uploadDataToCloudKit(_ sender: NSButton) 
        // Get CloudKit container and Public Database
        let myContainer = CKContainer.default()
        let publicDB = myContainer.publicCloudDatabase

        // Create array of cloudkit records so we can save a batch
        var cloudRecords = [CKRecord]()

        let groups = PayCodes().groups

        // For each PayCode Group...
        for payCodeGroup in groups 
            // Create CKRecord and give it a type
            let payCodeGroupRecord = CKRecord(recordType: "payCodeData")

            // For each PayCode in the group...
            for payCode in payCodeGroup.payCodes 
                // Fill the new CKRecord with key/value pairs
                payCodeGroupRecord.setObject(payCodeGroup.title as NSString, forKey: "group")

                if let commercialID = payCode.id.commercial as NSString?, let residentialID = payCode.id.residential as NSString? 
                    payCodeGroupRecord.setObject(commercialID, forKey: "commercialID")
                    payCodeGroupRecord.setObject(residentialID, forKey: "residentialID")
                

                payCodeGroupRecord.setObject(payCode.title as NSString, forKey: "title")

                if let description = payCode.description as NSString? 
                    payCodeGroupRecord.setObject(description, forKey: "description")
                

                payCodeGroupRecord.setObject((payCode.includesTripCharge ? 1 : 0) as NSNumber, forKey: "includesTripCharge")
                payCodeGroupRecord.setObject((payCode.needsResolutionCode ? 1 : 0) as NSNumber, forKey: "needsResolutionCode")


                payCodeGroupRecord.setObject(payCode.pay.commercial as NSNumber, forKey: "commercialPay")
                payCodeGroupRecord.setObject(payCode.pay.residential as NSNumber, forKey: "residentialPay")

                // Save new CKRecord into the Array
                cloudRecords.append(payCodeGroupRecord)
            
        

        print("There are \(cloudRecords.count) records about to be saved...")
        // print(cloudRecords)
        // Create an operation to save the records
        let operation = CKModifyRecordsOperation(recordsToSave: cloudRecords, recordIDsToDelete: nil)

        operation.perRecordCompletionBlock =  savedRecord, error in
            guard error != nil else 
                print("There was an error: \(error!.localizedDescription)")
                return
            

            print("Saved a record into CloudKit")
        

        operation.modifyRecordsCompletionBlock =  savedRecords, deletedRecordIDs, error in
            guard error != nil else 
                print("There was an error: \(error!.localizedDescription)")
                return
            

            guard let savedRecords = savedRecords else  return 
            print("Saved \(savedRecords.count) records into CloudKit")
        

        // Run the operation
        publicDB.add(operation)
//        cloudRecords.forEach  record in
//            publicDB.save(record)  savedRecord, error in
//                guard error != nil else 
//                    print("There was an error: \(error!.localizedDescription)")
//                    return
//                
//                
//                guard let savedRecord = savedRecord else  return 
//                print("Saved a record: \(savedRecord.allKeys())")
//            
//        
    

【问题讨论】:

您是否收到任何打印声明? 您是否使用CKContainer accountStatus(completionHandler:) 方法验证了对容器的访问权限? 是的,我有:它可用。另一方面,我刚刚意识到为什么我没有收到任何错误消息。这是因为我的警卫声明很愚蠢……一个否定错误。不过,现在我已经修复了它,它给了我这个错误:There was an error: You can't save the same record twice: <CKRecordID: 0x608000034420; recordName=067A4A65-B2E5-4DEA-974D-7354849D7D59, zoneID=_defaultZone:__defaultOwner__>。但是,当我通过 CloudKit Dashboard 检查时,数据库中没有保存任何数据。知道可能是什么问题吗?谢谢。 您是否在仪表板中查看正确的容器? 是的,我是。我也只是重置了该容器中的开发环境。我假设如果公共数据库中有任何东西,这个动作就会清空它,对吧?好吧,我尝试再次以编程方式上传数据......它仍然给我同样的错误。 【参考方案1】:

重复记录的问题是您重复使用了CKRecord 实例。

变化:

for payCodeGroup in groups 
    // Create CKRecord and give it a type
    let payCodeGroupRecord = CKRecord(recordType: "payCodeData")

    // For each PayCode in the group...
    for payCode in payCodeGroup.payCodes 
        // Fill the new CKRecord with key/value pairs
        payCodeGroupRecord.setObject(payCodeGroup.title as NSString, forKey: "group")

到:

for payCodeGroup in groups 
    // For each PayCode in the group...
    for payCode in payCodeGroup.payCodes 
        // Create CKRecord and give it a type
        let payCodeGroupRecord = CKRecord(recordType: "payCodeData")

        // Fill the new CKRecord with key/value pairs
        payCodeGroupRecord.setObject(payCodeGroup.title as NSString, forKey: "group")

【讨论】:

噢,伙计。这很有意义。谢谢!所以......我解决了这个问题......我现在得到的错误说我有“我的容器的 BundleId 无效”。您的 BundleID 是否应该采用特定格式?比如,反向 DNS 表示法之类的?再次感谢,伙计。如果可以的话,我会接受你的回答……但我只有 13 个代表点 :( 您可以接受答案,但可能需要等待几分钟。代表不是接受您自己问题的答案的问题。至于容器问题,您的应用程序是否设置为使用 Xcode 中的默认容器? 知道了。它被接受了。是的;它设置为使用默认容器。不应该吗? 应该没问题。我想知道这是否是一个暂时的问题。几个小时前另一个人发布了同样的问题:***.com/questions/46144170/… 嗯。有可能。我想我会在几个小时后再试一次,看看会发生什么。再次感谢您的帮助,伙计。

以上是关于为啥 CloudKit 不允许我将任何记录保存到默认容器的公共数据库中?的主要内容,如果未能解决你的问题,请参考以下文章

为啥CKModifyRecordsOperation批量删除CloudKit中的记录不删除记录?

将 Cloudkit 资产用作 UIimage

SWIFT/CloudKit - 更新记录并将其保存回容器

将 CloudKit 记录保存到本地文件保存除 CKAsset 之外的所有字段

Cloudkit 公共数据库错误:“不允许写入操作”

CloudKit 上传很慢