web-dev-qa-db-ja.com

静的ライブラリでのObjective-Cカテゴリのリンク

IOSアプリケーション用のプラグインを開発しています。それを.aファイルにコンパイルして、メインのxcodeプロジェクトで使用します。

これまでのところ、このライブラリにUIDeviceクラスのカテゴリを作成しています。このライブラリを使用してメインプロジェクトを実行すると、認識されないセレクタが原因でクラッシュします

-[UIDevice platform]:認識されないセレクターがインスタンスに送信されました

プラットフォームは、カテゴリを介して追加した機能の1つです。

だから私はそれらの関数をまったくリンクしていないと思い、c関数をUIDeviceカテゴリと同じファイルに追加して、コードからそれを呼び出しました。

今回はメインプロジェクトは問題なく実行されました...だから私はおそらくそれが別のことだと思い、C関数を削除しました。しかし、見覚えのないセレクターが原因で再びクラッシュしました。

私の質問:同じファイルで宣言された関数を呼び出さない限り、なぜxcodeはカテゴリ定義を無視するのですか?

そのファイルから関数を呼び出すかどうかに関係なく、UIDeviceカテゴリのこれらのメソッドを含めるように変更できるxcode設定はありますか?

乾杯

37
micken

チェックアウト Building Objective-C static libraries with categories

Objective-Cは、各関数(またはObjective-Cではメソッド)のリンカーシンボルを定義していません。代わりに、リンカーシンボルはクラスごとにのみ生成されます。既存のクラスをカテゴリで拡張する場合、リンカはコアクラス実装とカテゴリ実装のオブジェクトコードを関連付けることを認識しません。これにより、結果のアプリケーションで作成されたオブジェクトが、カテゴリーで定義されたセレクターに応答しなくなります。

この問題を解決するには、スタティックライブラリに対してリンクしているターゲットが-ObjCオプションをリンカーに渡す必要があります。このフラグにより​​、リンカーはすべてのオブジェクトファイルをロードしますObjective-Cクラスまたはカテゴリを定義するライブラリ内。このオプションは通常、アプリケーションに追加のオブジェクトコードが読み込まれるため、実行可能ファイルが大きくなりますが、既存のクラスのカテゴリを含む効果的なObjective-C静的ライブラリを正常に作成できます。


重要:64ビットおよびiPhone OSアプリケーションの場合、-ObjCがカテゴリのみを含む静的ライブラリからオブジェクトファイルをロードできないようにするリンカーバグがあり、クラスはありません。回避策は、-all_loadまたは-force_loadフラグを使用することです。

ソース:@albertamg( 静的ライブラリでのobjective-cカテゴリのリンク

72
albertamg

同じ問題がありました。サブプロジェクトで定義されたカテゴリで定義されたメソッドにより、認識されないセレクタ例外が発生しました。 (実際、これはInterface BuilderでUILabelサブクラスを指定できないこととして現れました。XIBには、入力したクラスではなく、IBに表示されたクラス(UILabelまたはUIView、ドラッグしたものに応じて)が含まれていました。奇妙なXCodeバグのように見えました。)

私のために働いた解決策は-force_loadを使用することでした:

左側のパネルで、メインプロジェクト(ルートアイテム)を選択します。右側にPROJECTTARGETSが表示されます。 TARGETSを選択します。 「ビルド設定」(上部のバー)-「リンク」-「その他のリンカーフラグ」に移動し、サブプロジェクトがXXXXXと呼ばれると仮定して、そこに-force_load ${BUILT_PRODUCTS_DIR}/libXXXXX.aを追加します(アイテムには、デバッグとリリースの2つのサブアイテムがあります。が、この複合アイテムをクリックすると、デバッグとリリースの両方に影響する場合があります。

-force_loadは単一のライブラリに対して機能し、サブプロジェクトライブラリごとに個別の-force_loadを指定する必要がある場合があることに注意してください。