カテゴリを含む静的ライブラリとリンクすると、リンカーはすべてのカテゴリ コードを実行可能ファイルにコピーします。共有ライブラリとリンクすると、共有ライブラリのコード セグメント全体がプロセスのアドレス空間にマップされますが、遅延してページインされるため、すべてを使用しない限り、ディスクからすべてのカテゴリ コードを実際に読み取ることはできません。
しかし、それは実際にはこのページが話していることではないと思います。
リンク時ライブラリ
まず、アプリをリンクするようにリンカーに指示するライブラリについて説明します。
を考慮してくださいNSString
。このNSString
クラスは、Foundation フレームワークで定義されます。これは、GUI を持つプログラムと GUI を持たないプログラムで役立つ汎用クラスでいっぱいのフレームワークです。そのためNSString
、Foundation で定義されているクラスには、文字列をグラフィックス コンテキストに描画するためのコードが含まれていません。そのコードは (通常) 非 GUI アプリでは役に立たないからです。
AppKit フレームワーク (OS X 上) は GUI を管理します。GUI で文字列をグラフィック コンテキストに描画できると便利です。そのため、AppKit には、文字列を描画するためのメソッドを追加するカテゴリ onNSString
drawAtPoint:withAttributes:
が含まれています。UIKit (iOS 上) は同じことを行います (ただし、メソッドは少し異なります)。
したがって、OS X でプログラムを作成し、Foundation を使用するが AppKit を使用しない場合、プロセスは AppKitNSString
カテゴリをロードせず、 NSString
.
AppKit のような共有ライブラリの場合、最新のハードウェアでは価格はごくわずかです。
これで、静的にすることができる独自のライブラリで同じことができます。Twitter と対話するための「TwitterModel」ライブラリを作成するとします。アカウントやつぶやきなど、Twitter で見つけたものをモデル化するクラスがたくさんあります。ただし、ツイートを表示するための GUI を管理するためのコードは含まれていません。
代わりに、別のライブラリ「TwitterGUI」を作成します。これは、(さらに多くのクラスを定義することに加えて) カテゴリを使用して、「TwitterModel」ライブラリのモデル クラスにメソッドを追加します。
TwitterGUI と TwitterModel の両方にリンクするプログラムを作成すると、実行可能ファイルには両方のライブラリのすべての Objective-C コードが含まれます。ただし、コマンド ラインのみのプログラム (GUI なし) を作成し、それを TwitterModel にリンクするだけの場合、そのプログラムには GUI 関連のコードは含まれません。ああ、節約!
ランタイム ライブラリ
次に、リンカーにアプリをリンクするように指示しない共有ライブラリについて考えてみましょう。
dlopen
またはのような API を使用して、実行時に新しいコードをプロセスに動的にロードできます-[NSBundle load]
。ライブラリにカテゴリが含まれている場合、それらのカテゴリは実行中のプログラムのクラスに追加されます。
そのため、ユーザーがアプリを実行するときにユーザーのシステムに共有ライブラリが存在する場合は、ライブラリをプログラムで読み込もうとすることで、オプションでアプリに共有ライブラリを使用させることができます。成功した場合は、ライブラリで定義されていることがわかっている任意のカテゴリ メソッドを呼び出すことができます。(もちろん、ライブラリが提供するクラスがあればそれを使用できます。) ライブラリのロードに失敗した場合は、ライブラリからこれらのカテゴリ メソッドを呼び出さないように注意してください。
ただし、通常、動的読み込み API を使用してプラグインを読み込みます。プラグインは、基本クラスをサブクラス化するクラス、またはプラグインが実装するために特別に定義したプロトコルに準拠するクラスを提供します。そのクラスの名前を取得する必要があるだけで、そのインスタンスを作成し、基本クラスまたはプロトコルで定義したメッセージを送信します。