基本的にコードベースで(InterfaceBuilderを使わずに)構築している前提での話。。。

親view(この場合はViewControllerのview)へsubviewの追加を行う場合、
loadViewとviewDidLoadのどちらで書くべきか、書籍等でも記述が分かれているので
悩んでいたのですが、自分なりの解釈というか考え方をまとめました。

公式リファレンス(ViewControllerPGforiPhoneOS)によると、
ViewControllerのview管理は大きく
ロードサイクルとアンロードサイクルという独立した
サイクルで行われているとのこと。

ロードサイクルは
アプリからviewを要求された時にviewがまだ存在しない場合発生する。
アンロードサイクルは
アプリケーションがメモリ不足の警告を受けると発生する。

ロードサイクル:

  1.viewプロパティにviewが設定されていない場合、loadViewを呼び出す。

    1-1.loadViewをオーバーライドした場合
      loadViewの実装中でviewプロパティにnil以外をプログラマが設定する必要がある。

    1-2.loadViewをオーバーライドしない場合
      ViewControllerのnibNameプロパティとnibBundleプロパティを使用して、
      指定のnibファイルからビューをロードしようとする。
      上記の処理でビューが見つからない場合、
      ViewControllerの名前と同名のnibファイルを検索、そのファイルをロードする。
      該当するnibファイルが見つからなければ、
      メソッドは空のUIViewオブジェクトを作成して、viewプロパティに代入する。

  2.viewDidLoadを呼び出す。(ロード時に必要な付加処理を行う。)

アンロードサイクル:

  1.アプリケーションがシステムからメモリ不足の警告を受け取る。

  2.ViewControllerはdidReceiveMemoryWarningを呼び出す。
    ビューを解放しても安全だと判断された場合のみ、ビューが解放される。

  3.ViewControllerはビューを解放するとviewDidUnLoadを呼び出す。
    このメソッドをオーバーライドすることで使用していたオブジェクトを
    解放する事が出来る。

リファレンスによると大きくこのような流れらしいです。
つまり、loadViewはあくまでViewControllerのviewプロパティを
間違いなくnil以外にするための処理で、
コードベースでviewを作成する場合はここでそのviewを作成する。

その他の初期化処理はviewDidLoadでするのが想定されている動き(だと思う。)
実際はloadViewとviewDidLoadは一連の流れで
呼び出されるようなのでどちらに書いても動きはする。

ただし,loadVIewをオーバーライドし、
実装中で[super loadView]もコールせず self.view 等とするとエラーになる。
(viewプロパティに値が未設定状態のため。)

ただ、アンロードサイクルを見ると、メモリが不足した際にアプリは
didReceiveMemoryWarningを呼び出し、
ビュー解放時にはviewDidUnLoadをコールする。
解放される範囲はviewDidLoadで作成したオブジェクトに限定される。
つまり、loadViewで作成したオブジェクトは範囲外となる。

長くなりましたが、この辺りを考慮すると
subviewの作成はviewDidLoadで行った方が良いという事ですかね。