根掘り葉掘りload initilzeメソッド

3891 ワード

まず、アプリケーションが起動した後、何をしたかを理解します.
main.mのmain()はプログラムのエントリですが、main関数に入る前にプログラムは多くのコードを実行します(そうでなければそんなに長く起動しません).プログラム依存のダイナミックリンクライブラリをメモリロード実行可能ファイルにロードするすべてのシンボル、コードruntimeはコンパイルされたシンボルコードを解析し、すべてのClassを遍歴し、継承レベルでClassのloadメソッドとそのCategoryのloadメソッドを順次呼び出す.
詳しい手順はsunnyxx大神のこの文章を参考にすることができます.

Load


Loadメソッドは、ファイルがプログラムによってロードするときに呼び出される.つまりCompile Sourceに表示されるファイルです.このクラスが使用されるかどうかは関係ない.

呼び出しルール


2016-11-11 14:28:39.807 [1734:818024] +[FatherViewController load]
2016-11-11 14:28:39.808 [1734:818024] +[SonViewController load]
2016-11-11 14:28:39.808 [1734:818024] +[ViewController load]
2016-11-11 14:28:39.808 [1734:818024] +[AppDelegate load]
2016-11-11 14:28:39.808 [1734:818024] +[ClassMian load]

2016-11-11 14:28:39.809 [1734:818024] +[SonViewController(Category_son) load]
2016-11-11 14:28:39.809 [1734:818024] +[FatherViewController(Category_01) load]
2016-11-11 14:28:39.809 [1734:818024] +[ViewController(Category) load]


興味があれば、Build PhasesのCompile Sources呼び出しの下で各ファイルの順序を自分で作成して、様々な場合のloadの呼び出し順序を試してみましょう.主にあまりにも技術の含有量がなくて、これらを詳しく書きません==

結論

  • 子クラスのloadを実行する前に、親クラスがロードされていない場合に、親クラスのloadメソッドを実行します.
  • 分類のloadメソッドは、最終実行
  • で上記2つを優先的に満たし、さらにCompile Sourcesの順序でloadメソッドを実行することを満たす.
  • load , load load , load 。 load , , load 。

    initialize


    この方法は、あるクラスにメッセージを最初に送信ときに呼び出す(インスタンス化オブジェクト)、一度だけ呼び出す.このクラスメソッドは不活性呼び出しであり、クラスがずっと使用されていない場合、このメソッドは実行する.

    Initiialzeメソッドの実行順序

    **2016-11-11 15:19:18.029 [1850:1017547] +[FatherViewController load]** **2016-11-11 15:19:18.031 [1850:1017547] +[FatherViewController(Category_01) initialize]** **2016-11-11 15:19:18.031 [1850:1017547] +[SonViewController(Category_son) initialize]** **2016-11-11 15:19:18.031 [1850:1017547] +[SonViewController load]** **2016-11-11 15:19:18.031 [1850:1017547] +[ViewController load]** **2016-11-11 15:19:18.031 [1850:1017547] +[AppDelegate load]** **2016-11-11 15:19:18.031 [1850:1017547] +[mianClass load]** **2016-11-11 15:19:18.032 [1850:1017547] +[SonViewController(Category_son) load]** **2016-11-11 15:19:18.032 [1850:1017547] +[FatherViewController(Category_01) load]** **2016-11-11 15:19:18.032 [1850:1017547] +[ViewController(Category) load]** **2016-11-11 15:19:18.032 [1850:1017547] +[AppDelegate initialize]** **2016-11-11 15:19:18.085 [1850:1017547] +[ViewController(Category) initialize]**

    その結果、FatherViewController(Category_01) initializeが先に実行する、SonViewController(Category_son) initializeが実行され、SonViewController loadが最後に実行する.すなわちloadメソッドがまだ実行するもこのクラスの使用に影響を与えない.

    次にinitializeメソッドの継承問題を見てみましょう


    上記の印刷結果から、 initialize initialize。 category load , initialize 。は、サブクラスのinitializeコメントを、そのinitialzeメソッドを書き換える
    + (void)initialize { NSLog(@" :%@  :%s",NSStringFromClass(self), __func__);}

    子クラスは親クラスのinitializeを継承します.親のinitializeメソッドを実行し、子のinitializeメソッドを実行する準備をすると、継承チェーンに基づいて親のinitialize実行が見つかります.

    いつinitializeを使うか


    initializeメソッドは、主に、NSMutableArrayなどのコンパイル期間の初期化に不便なオブジェクトに値を割り当てるために使用されます.このメソッドを使用する場合、dispatch_を追加する必要があるかどうかを複数回呼び出されることに注意する必要があります.once.

    まとめ


    1.loadおよびinitializeの方法は、いずれもインスタンス化対象の前に呼び出され、main関数を分水嶺とし、loadはmianの前、initializeはmainの後である.2.loadおよびinitializeの方法で親を呼び出す方法は、暗黙的な自動呼び出しである、子がinitializeメソッドを実装していなくても親を呼び出す方法であり、loadの方法では親を呼び出すことはない.3.load法はしばしば黒魔法の実現に用いられ、initialize法はグローバル変数4を初期化するために用いる.load initializeメソッドはすべてスレッドが安全です!複雑な操作を避ける必要がある.