我有一个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
答案 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:)
参数,而中间一个参数必须是代表键路径或属性名称的字符串。