#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 является вложенным необязательным — он равен нулю и не равен нулю:
Таким образом, изменение функции, подобное этому, не помогает:
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
}