ios - Swift CloudKit 保存记录 "Error saving record"

标签 ios swift ios8 cloudkit

我正在尝试将记录保存到 CloudKit 但出现错误。我在别处看到这是一个需要知道如何保存的问题,但我无法解决这个问题。

    var database:CKDatabase = CKContainer.defaultContainer().publicCloudDatabase
    var aRecord:CKRecord!

    if self.cloudId == nil {
        var recordId:CKRecordID = CKRecordID(recordName: "RecordId")
        self.cloudId = recordId // Setup at top
    }

    aRecord = CKRecord(recordType: "RecordType", recordID: self.cloudId)
    aRecord.setObject(self.localId, forKey: "localId")

    // Set the normal names etc
    aRecord.setObject(self.name, forKey: "name")

    var ops:CKModifyRecordsOperation = CKModifyRecordsOperation()
    ops.savePolicy = CKRecordSavePolicy.IfServerRecordUnchanged

    database.addOperation(ops)
    database.saveRecord(aRecord, completionHandler: { (record, error) in

        if error != nil {
            println("There was an error \(error.description)!")

        } else {
            var theRecord:CKRecord = record as CKRecord
            self.cloudId = theRecord.recordID
        }
    })

这给了我错误:

There was an error <CKError 0x16d963e0: "Server Record Changed" (14/2017); "Error saving record <CKRecordID: 0x15651730; xxxxxx:(_defaultZone:__defaultOwner__)> to server: (null)"; uuid = 369226C6-3FAF-418D-A346-49071D3DD70A; container ID = "iCloud.com.xxxxx.xxxx-2">!

不确定,因为我已经添加了 CKModifyRecordsOperation。遗憾的是,Apple 的文档中没有示例。我想念那个(你在 MSDN 上得到的)。

谢谢大家!

最佳答案

可以使用 CKDatabase 的便捷方法 saveRecord: 或通过 CKModifyRecordsOperation 将记录保存到 iCloud。如果它是单个记录,您可以使用 saveRecord:,但在将其保存回 iCloud 之前需要使用 fetchRecordWithID: 获取您要修改的记录。否则,它只会让你用新的 RecordID 保存一条记录。 More here.

database.fetchRecordWithID(recordId, completionHandler: { record, error in
    if let fetchError = error {
            println("An error occurred in \(fetchError)")
        } else {
            // Modify the record
            record.setObject(newName, forKey: "name")
        } 
}


database.saveRecord(aRecord, completionHandler: { record, error in
    if let saveError = error {
            println("An error occurred in \(saveError)")
        } else {
            // Saved record
        } 
}

上面的代码只是方向正确,但不会按原样工作,因为在 fetchRecordWithID 的 completionHandler 返回时,saveRecord 已经触发。一个简单的解决方案是将 saveRecord 嵌套在 fetchRecordWithID 的 completionHandler 中。一个可能更好的解决方案是将每个调用包装在一个 NSBlockOperation 中,并将它们添加到一个 NSOperationQueue 中,saveOperation 依赖于 fetchOperation。

这部分代码用于 CKModifyRecordsOperation,如果您只更新一条记录则不需要:

var ops:CKModifyRecordsOperation = CKModifyRecordsOperation()
ops.savePolicy = CKRecordSavePolicy.IfServerRecordUnchanged
database.addOperation(ops)

如果您确实使用 CKModifyRecordsOperation,您还需要设置至少一个完成 block 并在检测到与现有记录的冲突时处理错误:

let saveRecordsOperation = CKModifyRecordsOperation()

var ckRecordsArray = [CKRecord]()
// set values to ckRecordsArray

saveRecordsOperation.recordsToSave = ckRecordsArray
saveRecordsOperation.savePolicy = .IfServerRecordUnchanged
saveRecordsOperation.perRecordCompletionBlock { record, error in
    // deal with conflicts
    // set completionHandler of wrapper operation if it's the case
}

saveRecordsOperation.modifyRecordsCompletionBlock { savedRecords, deletedRecordIDs, error in
    // deal with conflicts
    // set completionHandler of wrapper operation if it's the case
}

database.addOperation(saveRecordsOperation)

除了使用 Objective-C 的 CloudKitAtlas 演示应用程序之外,还没有太多示例代码。希望这会有所帮助。

关于ios - Swift CloudKit 保存记录 "Error saving record",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24600308/

相关文章:

ios - 多个设备上的 Facebook 身份验证 token

ios - 让一个按钮检查之前是否按下了另一个按钮(Swift)

ios - 在模型中快速使用内部类是一种好习惯吗?

ios - ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering 不工作

ios - 在 UITextView 上以编程方式禁用 iOS8 Quicktype 键盘

ios - Swift:如何使用 Sprite 套件游戏实现额外的 View Controller ?

ios - 谷歌 OAuth 登录错误 : Invalid credentials

ios - 为什么建议的 Swift 单例实现使用结构?

ios - 如何动态添加swift字典中的值

objective-c - 更新 UILabel 会重置我在 xCode iOS8 中的 View