私は this one のようないくつかの投稿を読みましたSwiftでのサブクラス化NSObject
の違いについて、または単にそのネイティブベースclass
とサブクラスはありませんが、それらはすべて少し古い投稿であり、このトピックについては明確ではありません。
NSObject
はいつサブクラス化する必要がありますか?サブクラス化しない場合とサブクラス化しない場合の実際の違いは何ですか?現在、Swiftの推奨事項は何ですか?
NSObjectに関するAppleのドキュメント は、導入として次のように述べています。
NSObjectは、ほとんどのObjective-Cクラス階層のルートクラスです。 NSObjectを介して、オブジェクトはランタイムシステムへの基本的なインターフェイスとObjective-Cオブジェクトとして動作する機能を継承します。
これが示唆するように、コードで導入された型のNSObjectをサブクラス化する必要があるその型のインスタンスがObjective-Cオブジェクト(または一部のクラス自体のように動作する必要がある場合)まれなケース)。
私は気づいていませんAppleいつサブクラスNSObjectにnotしないかについてガイダンスを提供 ダイナミックディスパッチを減らすことを示唆 =または、サブクラス化に依存しないが protocolextensions を使用してコードを再利用するパラダイムを提示します。つまり、一般に静的なディスパッチと value type であるコードの再利用フレンドリー)。ほとんどのSwiftプログラマーはAppleからヒントを得ており、Swift言語機能をNSObjectベースの型がつまり、原則として、Objective-Cのダイナミズムが実際に必要な場合、最も一般的にはCocoa APIとのインターフェースが必要な場合にのみ、NSObjectベースの型を導入します。 (特に、コードがUI関連の場合に一般的です:たとえばビューコントローラー、ビュー)。
リンク先の質問への回答で指摘されているように 、Objective-Cスタイルのダイナミズム objc_msgSend
ベースのメソッドディスパッチのパフォーマンス 。 Swiftクラスのメソッドも仮想ですが、@objc
属性でメソッドを明示的にマークしない場合、特に-の場合、コンパイラはメソッドをディスパッチするより高速な手段を使用できます。 モジュール全体の最適化がオンになっています 、さらにSwift 3 where クラスは、タイプを定義するモジュール以外のサブクラス化のためにデフォルトで開いていません 。
NSObjectを回避するだけでなく、Swiftを作成するときに、クラスベースの参照タイプを完全に回避することもできます 多くの場合 。たとえば、上記のリンクされている値タイプのWWDCビデオ、または例として このブログ投稿 を紹介として見てください。簡単に言えば、値の型を使用すると、適切なローカル推論が可能になり、動的なメモリ割り当てと参照カウントのオーバーヘッドを回避できます(普遍的ではありませんが、参照型をフィールドとする構造体は注意点です)。
NSObject
をサブクラス化する必要があるもう1つのケースは、サブクラスをKVOのオブザーバーにしたい場合です。
addObserver(_ observer: NSObject, forKeyPath keyPath: String, options: NSKeyValueObservingOptions = [], context: UnsafeMutableRawPointer?)
オブザーバーはNSObject
(または配列またはセット)である必要があります。