Как проверить, равен ли nested optional нулю в универсальном классе?

#swift #generics #optional

#swift #общие #тип параметра

Вопрос:

У меня простой класс:

 class Values<T> {
    let new: T
    let old: T?

    init(new: T, old: T? = nil) {
        self.new = new
        self.old = old
    }

    func changed<TProp: AnyObject>(_ getter: (T) -> TProp) -> Bool {
        return old == nil || !(getter(old!) === getter(new))
    }

    func changed<TProp: Equatable>(_ getter: (T) -> TProp) -> Bool {
        return old == nil || !(getter(old!) == getter(new))
    }
}
  

При использовании его как Values<ChartViewModelData?> где ChartViewModelData — это класс, у меня возникли проблемы, когда old является вложенным необязательным — он равен нулю и не равен нулю:

консоль xcode

Таким образом, изменение функции, подобное этому, не помогает:

 return old == nil || old! == nil || !(getter(old!) === getter(new))
  

значение nil не должно передаваться в функцию получения, и я не знаю, как этого добиться.

Воспроизвести:

 class PropClass {}

class TestClass {
    var someProp = PropClass()
}

let values = Values<TestClass?>(new: TestClass(), old: Optional<Optional<TestClass>>(nil))
values.changed({ $0!.someProp }) /* Fatal error: Unexpectedly found nil while unwrapping an Optional value */
values.changed({ $0?.someProp }) /* error: cannot convert value of type '(TestClass?) -> PropClass?' to expected argument type '(TestClass?) -> _' */
  

Появляется вторая ошибка, потому что он не может использовать === для двух необязательных.

Комментарии:

1. Что именно getter делает?

2. @Alexander возвращает некоторое свойство объекта, а измененная функция возвращает, было ли оно изменено в новом значении при сравнении со старым.

3. Можете ли вы дать нам несколько тестовых примеров для работы?

4. если значения.изменены ({ $ 0!.chart }) { // изменена диаграмма обработки}

5. Я думаю, что в old! == nil коде вызывается == перегрузка типа (X?, X?) -> Bool , где тип времени выполнения X равен T? , что заставляет оператор фактически иметь тип (T??, T??) -> Bool , и сравнивается Optional.some(Optional.none) и Optional.none , которые не эквивалентны.

Ответ №1:

Только что потратил пару часов на поиски решения аналогичной проблемы, и я думаю, что наконец нашел его. Чтобы проверить, является ли вложенное значение nil для универсального типа, вы можете использовать это:

 if (newValue as AnyObject) is NSNull { 
    //value is nil
}