お問い合わせはこちらです。いつ#importを使用し、いつ@classを使用しますか?
簡単な答え:あなた#import
または#include
身体的な依存関係がある場合。そうでなければ、あなたは(前方宣言を使用し@class MONClass
、struct MONStruct
、@protocol MONProtocol
)。
身体依存の一般的な例をいくつか示します。
- 任意のCまたはC ++値(ポインターまたは参照は物理的な依存関係ではありません)。を
CGPoint
ivarまたはプロパティとして持っている場合、コンパイラは次の宣言を確認する必要があります。CGPoint
ます。
- あなたのスーパークラス。
- 使用する方法。
@class宣言を使用すると、次のような一般的なコンパイラ警告が表示されることがあります。「警告:レシーバー 'FooController'は転送クラスであり、対応する@インターフェイスが存在しない可能性があります。」
この点に関して、コンパイラーは実際には非常に寛大です。ヒント(上記のものなど)をドロップしますが、それらを無視して#import
適切に実行しないと、スタックを簡単に破棄できます。必要がありますが(IMO)、コンパイラーはこれを強制しません。ARCでは、コンパイラは参照カウントを担当するため、より厳密です。コンパイラーは、呼び出した不明なメソッドを検出すると、デフォルトにフォールバックします。すべての戻り値とパラメータはと見なされますid
。したがって、これは物理的な依存と見なされるべきなので、コードベースからのすべての警告を根絶する必要があります。これは、宣言されていないC関数の呼び出しに似ています。Cでは、パラメーターはint
。
前方宣言を優先する理由は、依存関係が最小限であるため、要因によってビルド時間を短縮できるためです。前方宣言を使用すると、コンパイラーは名前があることを認識し、物理的な依存関係がない場合にクラス宣言またはそのすべての依存関係を確認せずにプログラムを正しく解析およびコンパイルできます。クリーンビルドは時間がかかりません。インクリメンタルビルドは時間がかかりません。確かに、結果として、必要なすべてのヘッダーがすべての翻訳に表示されることを確認するためにもう少し時間を費やすことになりますが、これはビルド時間の短縮にすぐに役立ちます(プロジェクトが小さくない場合)。
#import
またはを使用する場合#include
、必要以上に多くの作業がコンパイラで発生します。複雑なヘッダーの依存関係も導入しています。これはブルートフォースアルゴリズムにたとえることができます。すると#import
、大量のメモリ、ディスクI / O、およびソースを解析およびコンパイルするためのCPUを必要とする大量の不要な情報をドラッグしていることになります。
NSObject
型は決して値ではないため、ObjCは依存関係に関してCベースの言語にとって理想にかなり近いです-NSObject
ます。型は常に参照カウントポインターです。したがって、プログラムの依存関係を適切に構成し、可能な限り転送することで、物理的な依存関係がほとんど必要ないため、コンパイル時間を大幅に短縮できます。依存関係をさらに最小限に抑えるために、クラス拡張でプロパティを宣言することもできます。これは、大規模なシステムにとって大きなメリットです。大規模なC ++コードベースを開発したことがあれば、その違いがわかるでしょう。
したがって、私の推奨は、可能な限りフォワードを使用してから#import
、物理的な依存があるところに使用することです。身体的依存を示唆する警告または別のメッセージが表示された場合は、すべて修正してください。修正は#import
、実装ファイルを修正することです。
ライブラリを構築するとき、いくつかのインターフェイスをグループとして分類する可能性があります。その場合#import
、物理的な依存関係が導入されているライブラリ(たとえば#import <AppKit/AppKit.h>
)になります。これにより依存関係が発生する可能性がありますが、ライブラリのメンテナは必要に応じて物理的な依存関係を処理できることがよくあります。機能を導入すると、ビルドへの影響を最小限に抑えることができます。