2011年8月12日金曜日

[NSObject load] と [NSObject initialize] の違い

クラスがObjective-Cのランタイムにロードされ利用可能になったタイミングで、そのクラス全体の初期化を行いたいということはよくあると思います。Objective-CではNSObjectクラスの以下のメソッドを用いてクラス全体の初期化を行うことができます。
  • + load
  • + initialize
この2つですが、結構挙動が異なります。詳細については以下のとおり。
http://cocoawithlove.com/2008/03/cocoa-application-startup.html
  • loadメソッドはクラスがロードされて利用可能になったら即座に呼び出される。
    • このとき、自分以外の他のクラスはまだロードされていない可能性があるので、自分以外のクラスを利用するような初期化はできない。
    • main関数の内部のNSAutoReleasePoolが用意されるよりも先に呼び出されるので、autoreleaseを使うような初期化を行う場合には自分でNSAutoReleasePoolを生成して管理する必要がある
  • initializeメソッドはそのクラスに実際のアクセスが最初に発生したタイミングで呼び出される。
    • 要するに一度も使われないクラスでは呼び出されない。
    • 自分以外のクラスもロードが完了しているので、自由に他のクラスを利用できる。
    • autoreleaseについても特に気にしなくて良い。
基本はinitializeメソッドを使うほうがより安全で確実なうえに、使われないなら初期化されないので経済的でいい感じです。こちらを使うことをお勧めします。

またloadメソッドについては、iOS実機で自家製frameworkを使っているを使っているとき、framework内部にビルドされているクラスのloadメソッドが呼び出されないという問題があります(静的ライブラリ.aについては未検証)iOSシミュレータおよびMacではきちんとframeworkに含まれているクラスについてもloadメソッドが呼び出されるのですが・・・ともかく地雷が大きいので避けたほうが懸命です。