Хорошо, я добавлю это к моему ответу !! Благодарю. Небольшое соображение для решения проблемы таким способом заключается в том, что вы теряете немного ясности относительно того, почему свойство непосредственно помечено

ользую NSPredicate для фильтрации массива в Swift. Проблема заключается в том, что после обновления до iOS 11 (Xcode 9 / w Swift 4) у меня продолжает появляться сбой в строке фильтра. Вот журнал сбоев:

Завершение работы приложения из-за необработанного исключения NSUnknownKeyException, причина:> '[valueForUndefinedKey:]: этот класс не является ключом> значение, совместимое с кодировкой для имени ключа.'

Вот пример класса, который у меня есть массив:

final class Model: NSObject {
    let name: String
    init(name: String) {
        self.name = name
    }
}

Вот код, который дает сбой:

let myArray = [Model(name: "Jason"), Model(name: "Brian")]
let predicate = NSPredicate(format: "name == 'Jason'")
let filteredArray = myArray.filter { predicate.evaluate(with: $0)}

Вопрос в том, почему происходит сбой, когда я обновился до iOS 11?

Ответы на вопрос(1)

Решение Вопроса

Тонкость обновления до Swift 4 заключается в том, что классы, которые являются подклассами NSObject, больше не подвергаются неявному воздействию Objective-C, как раньше. Из-за этого вам нужно явно аннотировать классы / функции с помощью @objc. Компилятор уведомит вас о местах, где нужна аннотация, но не в этом случае.

В конечном итоге из-за этого поиск значения ключа больше не был неявным образом выставлен target-c, который необходим для фильтрации с помощью NSPredicate. Код ниже исправляет сбой!

Решение 1

extension Model {
    @objc override func value(forKey key: String) -> Any? {
        switch key {
        case "name":
            return name
        default:
            return nil
        }
    }
}

Решение 2

Альтернатива благодаря Uros19: вместо реализации вышеуказанной функции вы можете аннотировать свойство напрямую с помощью @objc (например,@objc let name: String). Вы теряете немного ясности относительно того, почему вы аннотируете свойство с помощью @objc, но это лишь небольшое соображение.

Я надеюсь, что это экономит время и разочарование некоторых людей :)

 jason z05 окт. 2017 г., 15:44
Хорошо, я добавлю это к моему ответу !! Благодарю. Небольшое соображение для решения проблемы таким способом заключается в том, что вы теряете немного ясности относительно того, почему свойство непосредственно помечено@objc.
 Uros1903 окт. 2017 г., 00:21
Спасибо за это. В случае, если у кого-то есть модель с большим количеством свойств, используемых для предиката, и получите эту проблему (как я сделал). Вы можете просто добавить @objc перед объявлением свойства. например@objc var name: String, так что вы избежите длинного распределительного шкафа.

Ваш ответ на вопрос