5

プロジェクト内にテストクラスがあり、開発フェーズ中にありますが、アプリストアのビルド用にコンパイルされます。

NSClassFromStringを使用して、次のようなサンプルコードでクラスが存在するかどうかを判断できることをいくつかの本で読みました。

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

ただし、これをプロジェクトで実行した後、SomeClassを含むソースファイルを削除したターゲットのリンクエラーが発生していることがわかりました。

したがって、私の結論は、クラスの有無を判断するためのこのメカニズムは、そのクラスが他のクラスを使用しているライブラリまたはソースファイル内にある場合にのみ役立ちます(この手法について言及している本には詳細がありません)。それとも私は何かが足りないのですか?

4

1 に答える 1

6

NSClassFromString名前付きクラスのランタイムを検索します。事実上、クラスが存在するかどうかを判別します。

[SomeClass someMethod]コンパイラがリンク先の何かが必要なように静的参照を正常に取得するには。

したがって、Foundationのようなものにリンクし、Appleがそこにクラスを追加すると、そのメカニズムが機能することは間違いありませんNSJSONSerialization

また、存在する場合と存在しない場合があるフレームワークに対して弱いリンクがある場合にも機能します。たとえば、Twitter.frameworkに対して弱いリンクを作成し、を使用することができます[TWRequest alloc] ...。TwitterフレームワークがまったくなかったiOS4でも、ビルドしてデプロイすることができます。

Appleは実際、ライブラリの保存方法をわずかに変更し、弱いリンクをif([TWRequest class])明示的に使用する代わりに、使用を許可するなどに移行しています。NSClassFromString

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

その場合、メタクラスへの文字通りの参照を避ける必要があります。したがって、次のようなことができます。

Class someClassMetaClass = NSClassFromString(@"SomeClass");

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

ヘッダーファイルが表示されている限り、コンパイラーはSomeClassポインターのタイプを指定できるようにし(とにかくバイナリーに入らないため)、公開されたインターフェイスに対して通常の自動完了と警告を提案できるようになります。Class直接ではなく、ランタイムから取得したへのポインタを介してメタクラスを常にアドレス指定するようにしてください。そうすれば、リンカーがフォローアップする必要のあるものは何もありません。

于 2012-12-11T00:00:39.140 に答える