Не удается запросить одну запись CloudKit по идентификатору записи UUID - PullRequest
0 голосов
/ 29 мая 2019

У меня есть приложение CloudKit, где записи хранятся локально в CoreData.При создании записи CoreData создается UUID и заполняется в системном поле recordName.Приложение создает и сохраняет записи в CoreData, а затем загружает записи в CloudKit.Это работает нормально.

Однако сейчас я пишу код для изменения записи и не могу получить запись по UUID recordName.Мне не удалось установить предикат для поиска только этой записи.Я могу получить все записи с помощью TRUEPREDICATE, а также получить одну запись из поля, созданного в типе записи CloudKit.Я создал поле с именем myRecordName, где храню тот же UUID, что и CloudKit recordName.Запрос с использованием 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 Ответ

1 голос
/ 29 мая 2019

Я никогда не использовал 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:), а средний должен быть строкой, представляющей путь ключа или имя атрибута.

...