【问题标题】:Saving Modified Data in CloudKit在 CloudKit 中保存修改后的数据
【发布时间】:2014-08-21 23:38:16
【问题描述】:

我一直在测试 CloudKit,因为我希望在 iOS8 发布时发布使用它的应用程序。使用下面的代码保存数据似乎很简单:

CKRecordID * recordID = [[CKRecordID alloc] initWithRecordName:@"basicRecord"];
CKRecord * record = [[CKRecord alloc] initWithRecordType:@"basicRecordType" recordID:recordID];
[record setValue:@"defaultValue" forKey:@"defaultKey"];
CKDatabase *database = [[CKContainer defaultContainer] publicCloudDatabase];
[database saveRecord:record completionHandler:^(CKRecord *record, NSError *error) {

    if (error) {
        NSLog(@"Error: %@", error);
    } else {
        NSLog(@"Record Saved!");
    }
}];

我没有收到任何错误。但是,如果我尝试再次运行代码,可能是因为我已将记录值更改为

[record setValue:@"newValue" forKey:@"defaultKey"];

我收到一个错误,引出了一个问题,我该如何保存修改后的数据。毕竟,这是将内容保存到云端的基本部分。错误如下,任何帮助将不胜感激,请随时询问更多信息。

Error: <CKError 0x17024afb0: "Server Record Changed" (14/2017); "Error saving record <CKRecordID: 0x144684a80; basicRecord:(_defaultZone:__defaultOwner__)> to server: (null)"; uuid = 182C497F-966C-418A-9E6A-5563BA6CC6CD; container ID = "iCloud.com.yourcompany.CloudKit">

【问题讨论】:

    标签: ios objective-c xcode icloud cloudkit


    【解决方案1】:

    保存记录后,获取它,以便返回的记录将具有 Cloudkit 添加的 RecordID

    然后在同一条获取的记录上,使用 setValue 更改您要更改的数据

    然后你可以使用 CFModifyRecordsOperation 在下面的示例中,cachedCKRecordsServiceCenter 包含从 cloudkit 获取的记录,这些记录中包含 CloudKit RecordID......

               //find this service center in the cached records
                for (_,serviceCenter) in (theModel?.cachedCKRecordsServiceCenter.enumerated())! //is data for logged in Co ONLY with NO Co name attached
                {
                    let name = serviceCenter["name"] as! String
                    returnValue = "Try Again"
                    if name == displayedRecordName
                    {
                        serviceCenter.setValue(displayedRecordName! + "_" + (theModel?.companyName)!, forKey: "name") //db values have Co name appended
                        serviceCenter.setValue(label2Text.text, forKey:"street1")
                        serviceCenter.setValue(label3Text.text, forKey:"street2")
                        serviceCenter.setValue(label4Text.text, forKey:"city")
                        serviceCenter.setValue(label5Text.text, forKey:"state")
                        serviceCenter.setValue(label6Text.text, forKey:"zip")
                        serviceCenter.setValue(label7Text.text, forKey:"phone")
                        serviceCenter.setValue(label8Text.text, forKey:"email")
                        serviceCenter.setValue(label9Text.text, forKey:"note")
    
                        let saveRecordsOperation = CKModifyRecordsOperation()
    
                        var ckRecordsArray = [CKRecord]()
                        // set values to ckRecordsArray
                        ckRecordsArray.append(serviceCenter)
    
                        saveRecordsOperation.recordsToSave = ckRecordsArray
                        saveRecordsOperation.savePolicy = .ifServerRecordUnchanged
    
                        appDelegate.locked = true
                        saveRecordsOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
                            if error != nil {
                                // Really important to handle this here
                                ////////print("ERROR: Unable to update Driver Location: Error= \(error)")
                                self.returnValue = "ERROR: Unable to update Driver Location: ERROR = \(error)"
                                self.appDelegate.locked=false
                            }
                            else
                            {
                                 ////print("Successfully updated Service Center")
                                self.appDelegate.locked=false
                                self.returnValue = "Successfully updated Service Center"
                                self.appDelegate.locked=false
    
                                //reget the data into the cach
                                self.theModel?.fetchServiceCenterFromCloudKit1()
                            }
    
                        }
    
                        CKContainer.default().publicCloudDatabase.add(saveRecordsOperation)
                    }
                }
    

    【讨论】:

      【解决方案2】:

      来自CKRecord的文档:

      新记录仅存在于内存中,直到您将它们明确保存到 iCloud。

      当您设置新值[record setValue:@"newValue" forKey:@"defaultKey"]; 时,您已经保存了记录,使其无效。

      您可以使用CKModifyRecordsOperation,在大多数情况下它可能更可取,但您不必这样做。只需使用新的CKRecord 获取您的数据,然后按照here 的描述将该记录输入saveRecord:

      【讨论】:

        【解决方案3】:

        这个错误可能是因为saveRecord:只对新记录或者比服务器上版本更新的记录起作用:

        此方法仅在以前从未保存过或比服务器上的版本更新时才保存记录。您不能使用此方法覆盖服务器上较新版本的记录。 CKDatabase docs

        修改现有记录(或记录集)的推荐方法是使用带有所需savePolicyCKModifyRecordsOperation 集来处理冲突:

        修改记录的字段后,使用这种类型的操作对象将这些更改保存到数据库中。 (...) 保存记录时,savePolicy 属性中的值确定在服务器上检测到冲突时如何继续。 CKModifyRecordsOperation docs

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多