さて、そろそろ自分たち専用のライブラリをつくろうか!と思った時に、すごい簡単なアプリを作るのにライブラリの中身を全部ロードされたらアプリの容量が無駄に増えて困る!ということに気づきました。 そこで、アプリの容量がstaticライブラリによってどれくらい変わるのかが気になったので、調べてみました。
ライブラリのリンク条件
まず、ライブラリがどうやってリンクされるのか を試してみました。 試した方法としてはこの4つです。
- ライブラリなし
- ライブラリをプロジェクトに追加
- ライブラリのヘッダファイルを#import
- ライブラリのクラスを実際に使う
その結果、なんと、次のようになりました.
ライブラリなし
111KB
ライブラリをプロジェクトに追加
111KB
ライブラリのヘッダファイルを#import
111KB
ライブラリのクラスを実際に使う
180KB
つまり、ライブラリを#importするまではアプリの容量が変わらず、ライブラリ内のクラスを実際に使って初めてリンクされるようです。 最近のリンカは賢いようですね!
どのクラスまでリンクされるか
つぎに、ライブラリ内のどのクラスまでリンクされるのかな〜と試してみました。 クラスAがクラスBを使っていれば、クラスAをリンクした時点でクラスBもリンクされました。 当たり前ですね。 しかし、逆に言うと全く関係のないクラスCはリンクされなかったということなので、 ライブラリ内でお互いの依存関係が複雑だと、余分なクラスをロードしてしまう可能性が高くなるということです。 できるだけ系統立ててライブラリを作るのがいいのかなと思います。
曲者のカテゴリ
おぉ 実はリンカ賢いじゃん!と意気揚々としていたら、落とし穴が少しだけありました。 その落とし穴は「カテゴリ」。 スタティックライブラリを作るとき、カテゴリをライブラリ内に作ってもリンクしてくれないというバグがあります。 それを防ぐためには、リンカのオプションに-all_loadをつけなければいけません。(apple公式情報) で、この-all_loadが曲者で、こいつはその名の通りライブラリ内のすべてのクラスをリンクします。 #importすらされていないクラスも、全く使われていないクラスもすべてリンクしてしまいます。 アプリの容量激増です。
ライブラリなし
111KB
ライブラリをプロジェクトに追加 + -all_load
496KB
なので、自分たちとしては「ライブラリ内ではカテゴリを使わない」という結論を出しました。 -all_loadを使わない範囲でライブラリを作るということです。
よりアプリの容量を小さく汎用ライブラリを作るために
というわけで、全体の結論としては、次のことを守ればいいのかなと思います!
- ライブラリはどんどん便利なものを追加してOK
- ライブラリ内のそれぞれの独立性を保つ
- ライブラリ内ではカテゴリを使わない(-all_loadを使わない)