无法通过recordName UUID查询单个CloudKit记录

时间:2019-05-29 05:17:20

标签: ios swift core-data cloudkit

我有一个CloudKit应用,其中记录存储在本地CoreData中。创建CoreData记录时,将生成UUID并将其填充到系统recordName字段中。该应用程序会在CoreData中创建并保存记录,然后将记录上传到CloudKit。效果很好。

但是,我现在正在编码以修改记录,并且无法通过recordName UUID来获取记录。我没有成功设置谓词以仅搜索该记录。我可以使用TRUEPREDICATE检索所有记录,也可以从以CloudKit记录类型创建的字段中检索一条记录。我创建了一个名为myRecordName的字段,在其中存储了与CloudKit recordName相同的UUID。使用myRecordName的查询可以正常工作。

我为下面的谓词展示了三种方法。如果p1和p2都未注释掉,则应用程序在运行时崩溃。我想我在这里缺少一些非常简单的东西。任何指导将不胜感激。 Xcode 10.2.1,iOS 12.2,已在真实设备上进行了测试。

如果未注释掉p1或p2或两者,控制台将显示:

  

***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'-[CKReference rangeOfString:]:   无法识别的选择器已发送到实例0x280878520'

func queryDatabase() {

    let recordZone = CKRecordZone(zoneName: "PrimaryZone")
    let recName = "0E763775-5AD3-4A50-BFB8-AC310180E8A2"

    let recID = CKRecord.ID(recordName: recName, zoneID: recordZone.zoneID)
    let searchRecord = CKRecord(recordType: "Patient", recordID: recID)

    let p1 = NSPredicate(format: "%K == %@", CKRecord.Reference(recordID: recID, action: CKRecord_Reference_Action.none))
    let p2 = NSPredicate(format: "%K == %@", CKRecord.Reference(record: searchRecord, action: CKRecord_Reference_Action.none))

    //let predicate = NSPredicate(format: "TRUEPREDICATE")
    let p3 = NSPredicate(format: "myRecordName = %@", recName)

    let query = CKQuery(recordType: "Patient", predicate: p3)
    let sortDescriptor = NSSortDescriptor(key: "lastNameText", ascending: true)
    query.sortDescriptors = [sortDescriptor]

    privateDatabase.perform(query, inZoneWith: recordZone.zoneID) { (results, error) in
        if error != nil {
            print("error querying database\(String(describing: error?.localizedDescription))")
        } else {

            DVC.ckRecords = results!
            //print(results!)
            print(DVC.ckRecords.first!)

        }//if error else
    }//perform query block

}//queryDatabase

1 个答案:

答案 0 :(得分:1)

我从未使用过CloudKit,所以也许我错了,但是……

两个问题代码行p1=p2=尝试使用格式字符串创建NSPredicate。每个格式字符串包含两个 var arg替换,也称为占位符%K%@。因此,要使此方法起作用,必须在格式字符串参数后加上两个参数:第一个是键路径,它应该是字符串(%K),第二个是其值的对象(%@ )。为了您的目的,关键路径可能只是属性名称。

但是您只提供了一个参数CKRecord.Reference,系统会尝试为第一个参数(属性名,字符串)解析该参数。您遇到的错误是系统在期望字符串时尝试解析诸如CKRecord.Reference之类的对象时发生的典型错误。 Swift可能是类型安全的,但老式的NSPredicate var args函数不是:)

要解决此问题(并转到下一个问题),应提供关键路径(参数名称)参数,如下所示:

let p1 = NSPredicate(format: "%K == %@", "recordID", CKRecord.Reference(recordID: recID, action: CKRecord_Reference_Action.none))
let p2 = NSPredicate(format: "%K == %@", "recordID", CKRecord.Reference(record: searchRecord, action: CKRecord_Reference_Action.none))

由于我不清楚您在做什么,因此您可能需要稍微调整这两行。但是要点是,给定格式字符串,您需要三个NSPredicate(format:)参数,而中间一个参数必须是代表键路径或属性名称的字符串。