我正在创建一个将记录保存到CloudKit的应用程序,并将数据本地存储在Core Data中。我确实可以在两个位置保存记录,但是当与iCloud的连接不可用或存在保存错误时,我需要能够处理错误。我以为我可以填充CKModifyRecordsOperation
完成块中的变量来区分,但这不起作用 - 即使进程成功,CloudKit保存的返回值也始终为false。我们的想法是首先保存到CloudKit,然后检索recordID并使用Core Data save保存它。
这是我的代码,我从一个按钮调用doTheComboSave()
。控制台输出低于代码。任何意见,将不胜感激。 Xcode 8.3.3,Swift 3,iOS 10。
func saveNewCloudKitRecord() -> Bool {
privateDatabase = container().privateCloudDatabase
recordZone = CKRecordZone(zoneName: "myPatientZone")
var blockSavedToCloudKit = false
let myRecord = CKRecord(recordType: "Patient", zoneID: (recordZone?.zoneID)!)
myRecord.setObject(firstNameTextField.text as CKRecordValue?, forKey: "firstname")
myRecord.setObject(lastNameTextField.text as CKRecordValue?, forKey: "lastname")
let parentRefID = CKRecordID(recordName: "047EBE6C-AB1C-0183-8D80-33C0E4AE228B", zoneID: (recordZone?.zoneID)!)
//
//bunch more record fields
//
let modifyRecordsOperation = CKModifyRecordsOperation(recordsToSave: [myRecord], recordIDsToDelete: nil)
modifyRecordsOperation.timeoutIntervalForRequest = 10
modifyRecordsOperation.timeoutIntervalForResource = 10
modifyRecordsOperation.modifyRecordsCompletionBlock = {
records, recordIDs, error in
if let err = error {
blockSavedToCloudKit = false
//create placeholder record name for later updating
} else {
blockSavedToCloudKit = true
self.currentRecord = myRecord
self.passedInCKRecord = myRecord
}//if err
}//modifyRecordsOperation
privateDatabase?.add(modifyRecordsOperation)
print("blockSavedToCloudKit is \(blockSavedToCloudKit)")
return blockSavedToCloudKit
}//saveNewCloudKitRecord
typealias SavedCompletion = (_ success:Bool) -> Void
func saveTwoFiles(completionHandler : SavedCompletion) {
let flag = saveNewCloudKitRecord()
print("flag is \(flag)")
completionHandler(flag)
print("completionHandler(flag) is \(flag)")
}//makeTheComboSave
func doTheComboSave() {
saveTwoFiles() { (success) -> Void in
print("saveTwoFiles is \(success)")
if success {
//will pass the CKRecord so core data can store the recordID and recordName
saveTheNewRecord()//this is the Core Data save
DispatchQueue.main.async {
self.performSegue(withIdentifier: "unwindToMasterViewController", sender: self)
print("Completion block has been run successfully.")
}//Dispatch
} else {
//create placeholder recordName for later updating
saveTheNewRecord()//this is the Core Data save
DispatchQueue.main.async {
self.performSegue(withIdentifier: "unwindToMasterViewController", sender: self)
print("Completion block has been run but the file save to CloudKit failed.")
}//Dispatch
}//if else
}//block
}//doTheComboSave
控制台输出:
blockSavedToCloudKit为false
标志为假
saveTwoFiles为false
completionHandler(flag)为false
已运行完成块,但保存到CloudKit的文件失败。
modifyRecordsOperation成功
currentRecordName是:B53DCFB8-0EFB-4E79-8762-FECCEFBA9BD8
答案 0 :(得分:0)
见上述Ichydon的评论。
saveNewCloudKitRecord()函数在completionHandler设置我想要使用的布尔值之前返回。整个想法是首先创建CloudKit记录,以便我可以检索recordName以存储在Core Data中,以便同步本地和云记录。
更好的方法是首先保存到Core Data,但是自己创建CKRecordID并在保存到CloudKit时将其提供给记录。
在保存核心数据记录的功能中:
let myRecordName = UUID().uuidString
然后返回该字符串以用作CloudKit保存的参数。
let myRecordID : CKRecordID = CKRecordID(recordName: myRecordName, zoneID: (recordZone?.zoneID)!)
let myRecord = CKRecord(recordType: "Whatever", recordID : myRecordID)
希望这有助于其他人。