xcode 在 CloudKit 中保存修改后的数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24509782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 05:09:08  来源:igfitidea点击:

Saving Modified Data in CloudKit

iosobjective-cxcodeicloudcloudkit

提问by Hyman Chorley

I have been testing out CloudKit as i wish to release an app using it when the release of iOS8 occurs. It seems simple enough to save data using the code below:

我一直在测试 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!");
    }
}];

and I receive no errors from this. However, if i try to run the code again, maybe because i have changed the record value to

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

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

I receive an error which begs the question, how do i go about saving a modified piece of data. After all, this is a fundamental part of saving things to the cloud. The error is below and any help would be greatly appreciated, don't hesitate to ask for further information.

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

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">

回答by Guto Araujo

This error is probably because saveRecord:works only for new records or records that are newer than the version on the server:

此错误可能是因为saveRecord:仅适用于新记录或比服务器上的版本新的记录:

This method saves the record only if it has never been saved before or if it is newer than the version on the server. You cannot use this method to overwrite newer versions of a record on the server. CKDatabase docs

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

The recommended approach to modify an existing record (or set of records) is to use a CKModifyRecordsOperationset with the desired savePolicyto deal with conflicts:

修改现有记录(或记录集)的推荐方法是使用具有处理冲突CKModifyRecordsOperation所需的集合savePolicy

After modifying the fields of a record, use this type of operation object to save those changes to a database. (...) When saving records, the value in the savePolicy property determines how to proceed when conflicts are detected on the server. CKModifyRecordsOperation docs

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

回答by Mojo66

From the docs of CKRecord:

来自CKRecord的文档:

New records exist only in memory until you explicitly save them to iCloud.

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

When you set the new value [record setValue:@"newValue" forKey:@"defaultKey"];you have already saved the record, making it invalid.

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

You can use CKModifyRecordsOperationand in most situations it might be preferrable but you don't have to. Just fetch your data using a fresh CKRecord, then feed that record into saveRecord:as described here.

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

回答by adamsde1

After you save the record, fetch it so that the retured record will then have the RecordID that Cloudkit added

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

Then on that same fetched record, use setValue to change the data you want to change

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

Then you can use CFModifyRecordsOperation In the example below, cachedCKRecordsServiceCenter contains the fetched records from cloudkit and those records have the CloudKit RecordID's in them......

然后你可以使用 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)
                }
            }