CloudKit modifyRecordsCompletionBlock 随机失败

CloudKit modifyRecordsCompletionBlock Fails Randomly

此应用使用 CloudKit 在本地设备上进行记录存储和核心数据。本地创建的记录保存到 Core Data。调用以下方法将本地创建的记录发送到 CloudKit。我在应用程序启动时以及应用程序从后台 returns 调用此方法。我还为调用此方法的测试阶段编写了一个按钮。

行为似乎完全随机。例如,如果我创建 10 条记录,其中一些会正确上传到 CloudKit,而一些会失败。如果我手动重新运行该方法,最终它们都会上传到 CloudKit。我一直无法确定成功或失败的任何模式。此时,我通过一种方法播种测试记录,该方法使记录除了 recordName(UUID) 和文本字段的后缀外都相同。

通过有限的测试,如果我只创建一条记录,它总是有效。

如果我只创建两条记录,偶尔会失败。

如果我创建五个记录,几乎总是失败。

在 modifyRecordsCompletionBlock 内部,无论上传是否成功,updateSavedToCloudKitSuccess() 和 cleanUpTmpFile() 总是正确完成。

我也试过增加超时,这完全没有区别。

如有任何指导,我们将不胜感激。 Xcode8.3.3iOS10Swift3

func saveNewCloudKitRecordFromCoreData( myRecordName : String ) {

    //get the Core Data record
    let patient = findPatientRecord(myRecordName: myRecordName)

    privateDatabase = container().privateCloudDatabase
    sharedDatabase = sharedContainer().sharedCloudDatabase
    recordZone = CKRecordZone(zoneName: "myPatientZone")

    let myRecordID : CKRecordID = CKRecordID(recordName: myRecordName, zoneID: (recordZone?.zoneID)!)

    let myRecord = CKRecord(recordType: "Patient", recordID : myRecordID)

    myRecord.setObject(myRecordName as CKRecordValue?, forKey: "myRecordName")
    myRecord.setObject(patient.firstName as CKRecordValue?, forKey: "firstname")
    //bunch more fields...

    let modifyRecordsOperation = CKModifyRecordsOperation(recordsToSave: [myRecord], recordIDsToDelete: nil)
    modifyRecordsOperation.timeoutIntervalForRequest = 10
    modifyRecordsOperation.timeoutIntervalForResource = 10

    modifyRecordsOperation.modifyRecordsCompletionBlock = {

        records, recordIDs, error in

        if let err = error {
            print("error in modifyRecordsOperation \(err.localizedDescription)")
            self.updateSavedToCloudKitSuccess(recordName: myRecordName, success: false)
            self.cleanUpTmpFile()
        } else {
            print("success in modifyRecordsOperation")
            self.currentRecord = myRecord
            self.updateSavedToCloudKitSuccess(recordName: myRecordName, success: true)
            self.cleanUpTmpFile()
        }//if err
    }//modifyRecordsOperation

    privateDatabase?.add(modifyRecordsOperation)

}//saveNewCloudKitRecordFromCoreData

控制台输出示例:

NOresults.count 是:7

修改记录操作成功

保存到CloudKit = true

modifyRecordsOperation 错误无法修改某些记录

保存到CloudKit = false

modifyRecordsOperation 错误无法修改某些记录

保存到CloudKit = false

modifyRecordsOperation 错误无法修改某些记录

保存到CloudKit = false

modifyRecordsOperation 错误无法修改某些记录

保存到CloudKit = false

修改记录操作成功

保存到CloudKit = true

修改记录操作成功

保存到CloudKit = true

根据 rmaddy 和 paulw11 的评论,我实现了 perRecordCompletionBlock,发现错误总是与 CKAsset 文件有关。我将查看是否在执行完成块之前清理了该临时文件。

每个记录完成块:“; dateCreated = "2017-08-21 22:20:25 +0000"; dateOfBirth = "2017-04-23 22:20:25 +0000"; 名字 = 名字 12; 姓氏 = ZLastName12; myRecordName = "7621A7BD-7D32-4984-8117-2189D6F40D5F"; 笔记 = "This is note number12"; patientlistparent = ""; 初级医师 = "Dr. Who12"; 桑= 123456789; }, recordType=患者>。错误:可选() modifyRecordsOperation 中的错误无法修改某些记录 saveToCloudKit = false

我通过将资产保存操作放入同步全局队列中解决了这个问题。

    DispatchQueue.global(qos: .userInitiated).sync {

        let tmpDir = NSTemporaryDirectory()
        let tmpFile = tmpDir.appending("test.png")
        let tmpFileURL = URL(fileURLWithPath: tmpFile)

        var asset : CKAsset?

        if patient.conditionImage != nil {
            let data = NSData(data: patient.conditionImage as! Data) as NSData
            do {
                try data.write(to: tmpFileURL, options: .atomic)
            } catch {
                print(error)
            }//do catch

            asset = CKAsset(fileURL: tmpFileURL)
        }//if there is a conditionImage

        myRecord.setObject(asset as CKRecordValue?, forKey: "conditionImage")

        DispatchQueue.main.async {
            //back on main
        }//
    }//DispatchQueue.global