web-dev-qa-db-ja.com

UIViewControllerの誕生のプロセスは何ですか(どのメソッドがどれに続きますか)?

initWithNibname:awakeFromNibloadViewviewDidLoadviewDidAppear:layoutSubviews、Iなど、オーバーライドする多くのメソッドがあります。これらのメソッドを呼び出す順序を決定することはできません。

そのうちの1つを「ハート」でオーバーライドします。

詳細な説明はありますか?

57
Geri

CocoaビューとviewController管理 で、舞台裏で多くのことが行われています。

1。 viewControllerオブジェクト

最も基本的には、viewControllerは汎用コントローラーオブジェクトです。初期化されて初めて割り当てられたとき、それに関連付けられたビューオブジェクトはありません。ビューは、必要な場合(および必要な場合)にのみインスタンス化されます。したがって、ビューを考慮しない場合、viewControllerのライフサイクルは他のオブジェクトと同じです。

UIViewController * myVC = [[UIViewController alloc] initWith...];
...
[myVC release];

ViewControllersに指定された初期化子は -initWithNibname:bundle: です。 nibを指定すると、viewControllerはそのnibからビューを自動的にロードし、定義したIBOutletを接続できます(詳細については以下を参照)。

2。ビューのロードとアンロード

ViewControllerは、必要に応じてビューをロードします。これは通常、-viewメソッドが初めて呼び出されたときに発生し、UIの初期化方法に応じて、プログラム内でいつでも発生する可能性があります。ビューは、UIの管理方法に応じて、プログラムの有効期間中に何度か破棄され、再ロードされる場合があります。 viewControllerがビューが必要であるがまだロードされていないことを識別した場合、-loadViewメソッドが呼び出されます。基本的なメッセージフローは次のようになります。

view
  loadView
  viewDidLoad

-viewメソッドをオーバーライドすると、-loadViewおよびviewDidLoadは自動的に呼び出されないことに注意してください。 -loadViewをオーバーライドする場合、must viewControllerのviewプロパティを設定します。それ以外の場合、-viewへの次の呼び出しは、ロードプロセスを再度トリガーします。

ビューは、viewプロパティをnilに設定するだけで、プログラムの有効期間中いつでもアンロードできます。ビューにスーパービューがない限り(つまり、現在アクティブビュー階層の一部ではない場合)、-didReceiveMemoryWarningのデフォルト実装はこれを自動的に行います。メッセージフローは次のとおりです。

view = nil
   viewDidUnload

2a。プログラムでビューをロードする

-loadViewをオーバーライドすることを選択した場合、ビュー、サブビュー、他のviewController、およびこれらのオブジェクト間の接続を任意の方法で作成できます。もちろん、これは、作成するオブジェクトに関するメモリ管理も担当することを意味します。サブクラスが-loadViewをオーバーライドする場合、nilnibNameの両方に対してbundleを使用して初期化する必要があります。

2b。ペン先からビューをロードする

Nibファイルを使用する場合、-loadViewのデフォルト実装は自動的にそのnibファイルを開き、オブジェクトをインスタンス化し、それらの間に接続を追加し、メモリ管理を処理します。

Nibファイルでは、裏で多くのことが行われるため、事態は少し複雑になります。 -awakeFromNibメソッドは、すべてのオブジェクトに対して呼び出されます。これは、nibファイルがロードされるときにインスタンス化され、nibファイル内の他のオブジェクトが完全にロードされる保証はありません。と呼ばれます。

3。ビューの表示

-viewWillAppear:-viewDidAppear:-viewWillDisappear:、および-viewDidDisappear:は、特に、あるビューから別のビューへのアニメーション化されたトランジション中に、ビューが画面上に表示または非表示されている場合にのみ呼び出されます。これらのメソッドは、プログラムの存続期間中に何度も呼び出される可能性があります。これは、ビューがナビゲーションスキームでスワップインおよびスワップアウトされるためです。

4。ビューレイアウト

-layoutSubviewsメソッドはnotUIViewControllerの一部です。 UIViewオブジェクトの境界が変更されたときに呼び出されます。プログラムでカスタムUIViewサブクラスを使用する場合、Cocoaのデフォルトの自動サイズ変更メソッドに依存する代わりに、このメソッドを使用してカスタムサブビューレイアウトを実行できます。

5。すべてをまとめる

複雑なため、このプロセスを実行するにはさまざまな方法がありますが、通常のタイムラインは次のようになります。

-[viewController initWithNibname:Bundle:]
-[viewController awakeFromNib]
-[viewController loadView]
-[view awakeFromNib]
-[viewController viewDidLoad]
-[viewController viewWillAppear]
-[viewController viewDidAppear]
...
-[viewController viewWillDisappear]  // user navigated away
-[viewController viewDidDisappear]
...
-[viewController viewWillAppear]     // user navigated back
-[viewController viewDidAppear]
...
-[viewController viewWillDisappear]  // user navigated away
-[viewController viewDidDisappear]
...
-[viewController setView:nil]        // memory warning, perhaps
-[viewController viewDidUnload]
...
-[viewController loadView]           // user navigated back
-[view awakeFromNib]
-[viewController viewDidLoad]
-[viewController viewWillAppear]
-[viewController viewDidAppear]
...
173
e.James

私は最近これを再訪し、テストプロジェクトを作成しました: https://github.com/Janek2004/ViewControllerTest

IOSシミュレーターでプロジェクトを実行して、UIViewControllerサブクラスメソッドの実行順序を確認します。ストーリーボードの代わりにNibファイルを使用するか、View Controllerをプログラムで読み込むと、順序が異なる場合があります。

  1. -[ViewController initWithCoder:]ペン先またはストーリーボードからデータをアーカイブ解除する
  2. -[ViewController awakeFromNib]Interface Builderアーカイブまたはnibファイルからロードされた後、サービスのためにレシーバーを準備します。
  3. -[ViewController loadView]このメソッドを直接呼び出さないでください。 View Controllerは、viewプロパティが要求されたが現在nilであるときにこのメソッドを呼び出します。このメソッドは、ビューをロードまたは作成し、それをビュープロパティに割り当てます。
  4. -[ViewController viewDidLoad]このメソッドは、View Controllerがビュー階層をメモリにロードした後に呼び出されます。
  5. -[ViewController viewWillAppear:]このメソッドは、受信者のビューがビュー階層に追加される直前、およびアニメーションを表示するように設定される前に呼び出されます見る。
  6. -[ViewController viewWillLayoutSubviews]ビューがサブビューをレイアウトしようとしていることをView Controllerに通知するために呼び出されます。ビューの境界が変更されると、ビューは位置を調整しますそのサブビューの。ビューがサブビューをレイアウトする前に、View Controllerでこのメソッドをオーバーライドして変更を加えることができます。
  7. -[ViewController viewDidLayoutSubviews]ビューがサブビューをレイアウトしたことをView Controllerに通知するために呼び出されます。 View Controllerのビューの境界が変更されると、ビューはそのサブビューの位置を調整し、システムがこのメソッドを呼び出します。ただし、呼び出されるこのメソッドは、ビューのサブビューの個々のレイアウトが調整されたことを示すものではありません。各サブビューは、独自のレイアウトを調整します。
  8. -[ViewController viewDidAppear:]ビューがビュー階層に追加されたことをView Controllerに通知します。このメソッドをオーバーライドして、ビューの表示に関連する追加のタスクを実行できます。

  9. -[ViewController viewWillDisappear:]ビューがビュー階層から削除されようとしていることをView Controllerに通知します。このメソッドはビューに応答して呼び出されますビュー階層から削除されます。このメソッドは、ビューが実際に削除される前、およびアニメーションが設定される前に呼び出されます。ビューがビュー階層に追加されたことをView Controllerに通知します。このメソッドをオーバーライドして、ビューの表示に関連する追加のタスクを実行できます。

  10. -[ViewController viewDidDisappear:]ビューがビュー階層から削除されたことをView Controllerに通知します。
36

プロセスのもう1つの重要な瞬間は、subviewでlayoutSubviewsが呼び出されることです。ストーリーボードで設定された制約が適用されたのはこの時点であり、すぐではありません。制約された座標に基づいて、ビューのサブビューを調整する必要がある場合は、layoutSubviewsで調整する必要があります。 viewDidLayoutSubviewsでそれを行うと、それらのサブビューにはまだ制約が適用されていないため(文書ごとに「各サブビューは独自のレイアウトの調整を担当するため」)、viewDidAppearで行う場合、サブビューが座標を変更するのをユーザーが見るため、明らかに遅すぎます。したがって、プロセスのもう1つの重要なステップは次のとおりです。

-viewController viewWillAppear
-viewController viewWillLayoutSubviews
-viewController viewDidLayoutSubviews
---> viewController.[any subview] layoutSubviews
-viewController viewDidAppear  
9
Harris

from Apple UIViewControllerドキュメント:

UIViewControllerの新しいサブクラスを定義するときは、コントローラーによって管理されるビューを指定する必要があります。これらのビューを指定するには、2つの相互排他的な方法があります。手動またはnibファイルを使用する方法です。ビューを手動で指定する場合、loadViewメソッドを実装し、それを使用してルートビューオブジェクトをビュープロパティに割り当てる必要があります。 nibファイルを使用してビューを指定する場合、loadViewをオーバーライドする必要はありませんが、代わりにInterface Builderでnibファイルを作成してから、initWithNibName:bundle:メソッドを使用してView Controllerオブジェクトを初期化する必要があります。 nibファイルを使用したビューの作成は、Interface Builderアプリケーションを使用してビューをグラフィカルに(プログラムではなく)作成および構成できるため、多くの場合より簡単です。ただし、両方の手法の最終結果は同じです。つまり、適切なビューのセットを作成し、それらをビュープロパティを通じて公開します。

私の頭の上から:

  1. initWithNibname
  2. loadView(手動でロードする)
  3. viewDidiLoad
  4. viewDidAppear

layoutSubviewsが入る手掛かりなし

4
LordT

私は通常、アプリ起動デリゲートを含むこれらすべてのデリゲートにNSLog(またはブレークポイント)を配置し、デバッガーの順序に従うことでこの問題を解決します。

1
hotpaw2
-これは表示のみに関連しています:
-viewWillAppear:
-viewDidAppear:
-viewWillDisappear:および
-viewDidDisappear:
 
は、ビューが表示されているときにのみ呼び出されます。
 
-viewController viewDidLoad 
-viewController viewWillAppear 
-viewController viewDidAppear 
 
他のメソッド
 
-viewController viewDidDisappear 
-viewController viewWillDisappear 
-viewController viewDidUnload 
1
Ram S

E.Jamesの優れた説明に感謝します。投稿にまだコメントすることはできませんが、簡単な視覚的説明については、View Controllerプログラミングガイドの このフローチャート を参照してください。そして、これはトピック外ですが、 アプリ起動シーケンスのグラフ については、iOS Application Programming Guideを参照してください。

0
Chris Conover