Swift 4 подход для observeValue (forKeyPath:…)

Я пытался найти пример, но то, что я видел, не работает в моем случае.

что было бы эквивалентом следующего кода:

object.addObserver(self, forKeyPath: "keyPath", options: [.new], context: nil)

override public func observeValue(
    forKeyPath keyPath: String?,
    of object: Any?, 
    change: [NSKeyValueChangeKey : Any]?, 
    context: UnsafeMutableRawPointer?) {

}

код выше работает, но я получаю предупреждение от SwiftLink:

предпочитаю новый блок на основе кво API с keypaths при использовании Свифт 3.2 или более поздней версии.

Я ценю это, если вы можете мне точку в правильном направлении.

2 ответов


Swift 4 представил семейство бетона типы ключевых путей новая Выражение Ключевого Пути для их производства и нового закрытия на основе наблюдать функция доступна для классов, которые наследуют NSObject.

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

self.observation = object.observe(\.keyPath) { 
    [unowned self] object, change in
    self.someFunction()
}

типы Вовлечен

грамматика ключевого пути

общие грамматика выражения ключевого пути следует за формой \Type.keyPath здесь Type - имя конкретного типа (ВКЛ. любые общие параметры), и keyPath цепочка из одного или нескольких свойств, индексов или необязательных цепочек / принудительных распаковок postfixes. Кроме того, если тип ключевого пути может быть выведен из контекста, его можно удалить, что приводит к наиболее содержательному \.keyPath.

это все допустимые выражения пути к ключу:

\SomeStruct.someValue
\.someClassProperty
\.someInstance.someInnerProperty
\[Int].[1]
\[String].first?.count
\[SomeHashable: [Int]].["aStringLiteral, literally"]!.count.bitWidth

собственности

вы владелец NSKeyValueObservation, например,observe функция возвращает значение, смысл, не нужно addObserver, ни removeObserver больше; скорее, вы держите сильную ссылку на него до тех пор, пока вам нужно ваше наблюдение наблюдения.

ты не требуется invalidate() либо: это будет deinit изящно. Таким образом, вы можете позволить ему жить, пока экземпляр, держащий его, не умрет, остановите его вручную niling ссылка, или даже вызвать invalidate() если вам нужно сохранить свой экземпляр в живых по какой-то вонючей причине.

предостережения

как вы могли заметить, наблюдение по-прежнему скрывается в пределах механизма KVO Cocoa, поэтому оно доступно только для классов Obj-C и Swift, наследующих NSObject (любимый тип каждого Swift-dev) с дополнительным требованием, чтобы любое значение, которое вы собираетесь наблюдать, должно быть отмечено как @objc (любимый атрибут каждого Swift-dev) и объявлено dynamic.

это, как говорится, общий механизм-это улучшение, особенно потому, что ему удается Swiftify соблюдая импортные NSObjects из модулей нам может потребоваться использовать (например. Foundation), и не рискуя ослабить выразительную силу, которую мы так упорно работаем, чтобы получить с каждым нажатием клавиши.

в качестве примечания,Ключ-Путь строка выражения обязаны динамического доступа к NSObject свойства KVC или call value(forKey(Path):)

за кво

существует гораздо больше выражений Key-Path, чем KVO. \Type.path выражения могут храниться как KeyPath объекты для последующего повторного использования. Они приходят в writable, частично и тип-стертые флейворы. Они могут увеличить выразительную силу функций геттера / сеттера, предназначенных для композиции, не говоря уже о роли, которую они играют в том, чтобы позволить людям с самым сильным желудком погрузиться в мир функциональных концепций, таких как линзы и призмы. Я предлагаю вам проверить ссылки ниже, чтобы узнать больше о многих дверях разработки, которые они могут открыть.

ссылки:

выражение пути ключа @ docs.swift.org

KVO docs @ Apple

Swift Evolution Smart KeyPaths предложение

игровая площадка Ole Begemann'S Whats-new-in-Swift-4 с примерами ключевых путей

WWDC 2017 Видео: Что нового в Foundation 4: 35 для SKP и 19: 40 для Кво.


чтобы добавить что-то к ответу, поскольку я испытал сбои в своем приложении при использовании этого метода в iOS 10.

в iOS 10 вам все равно нужно удалить наблюдателя перед освобождением класса или иначе вы получите сбой NSInternalInconsistencyException о том, что:

экземпляр A класса C был освобожден, пока ключевые наблюдатели стоимости все еще были зарегистрированы в нем.

чтобы избежать этой аварии. Просто установите свойство observer, которое вы использование to nil.

deinit {
    self.observation = nil
}