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
Saving Modified Data in CloudKit
提问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 CKModifyRecordsOperation
set with the desired savePolicy
to 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 CKModifyRecordsOperation
and 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)
}
}