1. ホーム
  2. iphone

[解決済み] 静的ライブラリのObjective-Cカテゴリ

2022-05-02 04:18:02

質問

iPhoneプロジェクトに静的ライブラリを正しくリンクさせる方法を教えてください。アプリのプロジェクトに直接依存する形で追加した静的ライブラリのプロジェクトを使用しており(ターゲット -> 一般 -> 直接依存)、すべて問題なく動作しているのですが、カテゴリ。静的ライブラリで定義したカテゴリがアプリで動作していません。

そこで質問ですが、いくつかのカテゴリを含む静的ライブラリを他のプロジェクトに追加するにはどうすればよいのでしょうか?

また、一般的に、他のプロジェクトのコードをアプリプロジェクトで使用する際のベストプラクティスは何でしょうか?

どのように解決するのですか?

解決方法 Xcode 4.2では、ライブラリに対してリンクしているアプリケーション(ライブラリそのものではない)に移動し、プロジェクトナビゲータでプロジェクトをクリックし、アプリのターゲットをクリックし、ビルド設定、"Other Linker Flags"を検索し、+ボタンをクリックして、'-ObjC'を追加するだけでよいです。'-all_load' と '-force_load' は不要になりました。

詳細はこちら 様々なフォーラム、ブログ、アップルドキュメントでいくつかの答えを見つけました。今、私が検索し、実験したことを簡単にまとめてみました。

問題の原因(アップルテクニカルQ&A QA1490より引用 https://developer.apple.com/library/content/qa/qa1490/_index.html ):

Objective-Cはリンカを定義しません。 のシンボルは、各関数(またはメソッド。 の場合) - その代わり、リンカーは シンボルが生成されるのは クラスがあります。既存のクラスを拡張する場合 カテゴリを持つクラスは、リンカが オブジェクトコードを関連付けることを知らない コアクラスの実装と を実装しています。このため で作成されたオブジェクトは を使用することができます。 で定義されているセレクタに カテゴリを作成します。

そして、その解決策。

この問題を解決するために、静的な ライブラリは、-ObjC オプションを渡す必要があります。 をリンカに渡す必要があります。このフラグにより リンカは を定義しているライブラリは Objective-Cのクラスまたはカテゴリ。一方 このオプションを使用すると、通常 実行ファイルのサイズが大きくなります。 にロードされるオブジェクトコード アプリケーションを作成することができます。 効果的な Objective-Cのスタティック・ライブラリで 既存のカテゴリーを含む クラスがあります。

また、iPhone開発FAQでも推奨されています。

すべてのObjective-Cをリンクするには クラスをスタティック・ライブラリに含めることができますか?静的ライブラリの その他のリンカーフラグのビルド設定 -ObjCです。

とフラグの説明です。

- オールロード 静的アーカイブ・ライブラリの全メンバーを読み込みます。

- ObjC を実装した静的アーカイブライブラリの全メンバーを読み込みます。 Objective-Cのクラスまたはカテゴリ。

- force_load (path_to_archive) 指定された静止画の全メンバーを読み込みます。 アーカイブライブラリ。注意: -all_load は、すべてのアーカイブのすべてのメンバーを強制的に がロードされます。このオプションで は特定のアーカイブを対象とします。

*アプリのバイナリサイズを小さくし、all_loadが引き起こす可能性のある競合を回避するために、force_loadを使用することができます。

はい、プロジェクトに追加された *.a ファイルで動作します。 しかし、私は、直接の依存関係として追加された lib プロジェクトで問題が発生しました。しかし、後で、それは私のせいであることがわかりました - 直接依存のプロジェクトが適切に追加されていない可能性があります。それを削除して、再びステップで追加すると、私はそれを削除します。

  1. libプロジェクトファイルをアプリプロジェクトにドラッグ&ドロップする(またはProject->Add to project...で追加する)。
  2. libプロジェクトのアイコンの矢印をクリックすると、mylib.aのファイル名が表示されるので、このmylib.aをドラッグして、ターゲット -> Link Binary With Libraryグループにドロップします。
  3. 拳ページ(General)でターゲット情報を開き、依存関係リストに私のlibを追加します。

私の場合、quot;-ObjC"フラグで十分でした。

のアイデアにも興味がありました。 http://iphonedevelopmentexperiences.blogspot.com/2010/03/categories-in-static-library.html ブログで紹介しています。著者は、-all_loadや-ObjCフラグを設定せずに、libからカテゴリを使用することができると言っています。彼は、カテゴリ h/m ファイルに空のダミークラス interface/implementation を追加して、リンカにこのファイルを使わせるだけです。そして、このトリックでうまくいった。

しかし、著者は、ダミーオブジェクトをインスタンス化していないとも言っています。カテゴリーファイルから明示的に本物のコードを呼び出す必要があることがわかりました。そのため、少なくともクラス関数は呼び出される必要があります。 そして、ダミークラスも必要ない。シングルCファンクションも同様です。

ということで、libファイルの書き方をすると

// mylib.h
void useMyLib();

@interface NSObject (Logger)
-(void)logSelf;
@end


// mylib.m
void useMyLib(){
    NSLog(@"do nothing, just for make mylib linked");
}


@implementation NSObject (Logger)
-(void)logSelf{
    NSLog(@"self is:%@", [self description]);
}
@end

そして、AppプロジェクトのどこかでuseMyLib();を呼び出すと であれば、どのクラスでもlogSelfカテゴリメソッドを使うことができる。

[self logSelf];

さらにテーマに沿ったブログを紹介

http://t-machine.org/index.php/2009/10/13/how-to-make-an-iphone-static-library-part-1/

http://blog.costan.us/2009/12/fat-iphone-static-libraries-device-and.html