私は、CloudKitにレコードを保存するアプリケーションを作成しており、そのデータをCore Dataにローカルに保存しています。私は実際に両方の場所にレコードを保存することができますが、iCloudへの接続が利用できない場合や保存エラーが発生した場合にエラーを処理できる必要があります。私はCKModifyRecordsOperation
コンプリートブロック内の変数を差別化するための変数を設定できると考えましたが、それはうまくいかない - プロセスが成功しても、CloudKitの保存からの戻り値は常に偽です。最初にCloudKitに保存してから、recordIDを取得し、コアデータの保存で保存します。CloudKitからBoolを返すCompletionHandlerが正しくない
ここに私のコードがありますが、私はをbarbuttonから呼び出します。コンソールの出力はコードの下にあります。アドバイスをいただければ幸いです。 Xcodeの8.3.3、スウィフト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ある偽
completionHandler(ありますフラグ)は偽です
完了ブロックは実行されましたが、CloudKitに保存されたファイルは失敗しました。
modifyRecordsOperation
で成功currentRecordNameです:B53DCFB8-0EFB-4E79-8762-FECCEFBA9BD8
CloudKit /ネットワークコールの非同期性を理解していないと思います。 saveNewCloudKitRecordから返されたfalseは、操作が完了する前に返されます。あなたは、あなたがあなたの例で期待する方法を返すために、障壁またはセマフォーを必要とします。 – agibson007