2012-12-10 6 views
5

開発段階でプロジェクト内にテストクラスがありますが、アプリケーションストアビルド用にコンパイルされます。条件付き呼び出しにNSClassFromStringを使用する方法を理解していません

私はNSClassFromStringは、クラスのようなサンプルコードで存在するかどうかを決定するために使用することができ、いくつかの本で読んだ

:しかし、私のプロジェクトでの練習にこれを入れた後、私は「ことがわかり

if (NSClassFromString(@"SomeClass") != nil) 
{ 
[SomeClass someMethod]; 
} 
else 
{ 
code not using SomeClass 
} 

SomeClassを含むソースファイルを削除したターゲットにリンクエラーが発生しました。

私の結論は、クラスの有無を判断するためのこのメカニズムは、そのクラスが他のクラスを使用しているライブラリまたはソースファイル内にある場合にのみ役立ちます(これについて言及している書籍技術)。 何か不足していますか?

答えて

6

NSClassFromStringは、指定されたクラスのランタイムを検索します。クラスが存在するかどうかは事実上決定される。

コンパイラが[SomeClass someMethod]のような過去の静的リファレンスを正常に取得するには、リンクする対象が必要です。

あなたは、FoundationとAppleのようなものにリンクするときにメカニズムが動作することは間違いありません。つまり、NSJSONSerializationが存在するかどうかのチェックのように、余分なクラスが追加されます。

フレームワークとのリンクが弱い場合や、存在しない場合もあります。だからTwitter.frameworkとの弱いリンクがあり、[TWRequest alloc] ...を使用することができます。 Twitterフレームワークがない場所でも、iOS 4を構築して展開することはできます。

アップルは実際にライブラリが保存されている方法を若干変更して、弱いリンクがあるNSClassFromStringの代わりにif([TWRequest class])などを使用できるように移行しています。

しかし、静的ライブラリにリンクするか、リンクしないように思えますか?したがって、クラスは実行時に利用可能である場合と利用できない場合がありますが、リンカに表示される場合と表示されない場合があります。

その場合、メタクラスへのリテラル参照を避けるだけで済みます。限りヘッダファイルは(つまり、とにかくバイナリに入らないため)となりますコンパイラはあなたが、ポインタのためにSomeClassタイプを指定できるように幸せになります表示されているよう

Class someClassMetaClass = NSClassFromString(@"SomeClass"); 

if(someClassMetaClass) 
{ 
    SomeClass *instance = [[someClassMetaClass alloc] init]; 
    /* ... */ 
} 

:だからあなたのような何かを行うことができます公開されたインターフェースに対して通常の自動補完と警告を提案することができます。ランタイムから直接取得するのではなく、Classへのポインタを使用して常にメタクラスのアドレスを指定するようにしてください。そうすれば、リンカーがフォローアップする必要はありません。

+0

ありがとうございました。私はライトバージョンからいくつかのクラスが欠けている "フル"と "ライト"のバリアントを持つライブラリを構築しています。他のいくつかのクラスの動作は、それらが存在するかどうかに依存します。 – Gruntcakes

関連する問題