web-dev-qa-db-ja.com

Swift observeValue(forKeyPath:...)の4つのアプローチ

私は例を見つけようとしてきましたが、私の場合は見たことがうまくいきません。

次のコードに相当するものは何ですか:

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から警告が表示されます。

Swift 3.2以降を使用する場合は、キーパスを使用した新しいブロックベースのKVO APIを優先してください。

あなたが私を正しい方向に向けることができれば感謝しています。

34
MXV

Swift 4は、具体的なファミリー Key-Path types 、新しい Key-Path Expression を導入し、新しいクロージャーベースの observe 関数を導入しましたNSObjectを継承するクラスで使用できます。

この新しい機能セットを使用すると、特定の例をより簡潔に表現できます。

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

関与するタイプ

キーパス文法

キーパス式の一般的な 文法 は、\Type.keyPathという形式に従います。ここで、Typeは具体的な型名(一般的なパラメータを含む)、keyPathは1つ以上のプロパティ、添え字のチェーンです、またはオプションのチェーン/強制的なアンラップ後置。さらに、keyPathのTypeをコンテキストから推測できる場合は省略でき、最も簡潔な\.keyPathになります。

これらはすべて有効なキーパス式です。

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

所有権

あなたはNSKeyValueObservation関数が返すobserveインスタンスの所有者です。つまり、する必要はありませんaddObserverremoveObserverもありません。むしろ、観察を観察する必要がある限り、それに対する強い参照を保持します。

あなたはnotのいずれかinvalidate()を必要としています:それはdeinitに優雅になります。そのため、それを保持しているインスタンスが死ぬまでライブにするか、参照をnilingすることで手動で停止するか、何らかの臭い理由でインスタンスを生き続ける必要がある場合はinvalidate()を呼び出すこともできます。

注意事項

お気づきかもしれませんが、観察はまだCocoaのKVOメカニズムの範囲内に潜んでいるため、NSObject(Swift-devのお気に入りの型すべて)を継承するObj-CクラスおよびSwiftクラスでのみ利用できます。観察するつもりなら、@objc(Swift-devのお気に入りの属性ごと)としてマークし、dynamicを宣言する必要があります。

そうは言っても、全体的なメカニズムは歓迎すべき改善です。特に、使用する必要があるモジュール(NSObjectsなど)からインポートされたFoundationをSwiftifyが監視し、表現力を弱めることなく取得するのが難しいためです。すべてのキーストロークで。

サイドノートとして、 Key-PathStringExpressions はまだ必要です 動的にアクセスNSObject 's KVCのプロパティ、またはvalue(forKey(Path):)の呼び出し

KVOを超えて

キーパス式には、KVOよりもはるかに多くのことがあります。 \Type.path式は、後で再利用するためにKeyPathオブジェクトとして保存できます。書き込み可能、​​部分消去、タイプ消去のフレーバーがあります。彼らは、レンズとプリズムのような機能的概念の世界を掘り下げることを可能にすることに加えて、作曲のために設計されたゲッター/セッター機能の表現力を増強することができます。以下のリンクをチェックして、開くことができる多くの開発の扉について詳しく知ることをお勧めします。

リンク:

Key-Path Expression @ docs.Swift.org

KVO docs @ Apple

Swift Evolution Smart KeyPathsの提案

キーパスの例があるOle BegemannのWhats-new-in-Swift-4プレイグラウンド

WWDC 2017ビデオ:Foundationの新機能SKPの場合は4:35、KVOの場合は19:4

76
Matias Pequeno

IOS 10でこの方法を使用すると、アプリでクラッシュが発生したため、答えに何かを追加します。

IOS 10では、クラスの割り当てを解除する前にオブザーバーを削除する必要があります。そうしないと、次のことを示すクラッシュNSInternalInconsistencyExceptionが発生します。

クラスAのインスタンスCは、キー値オブザーバーがまだ登録されている間に割り当て解除されました。

このクラッシュを避けるため。使用しているオブザーバープロパティをnilに設定するだけです。

deinit {
    self.observation = nil
}    
6
barbarity