モーダルおよび非モーダルの状況でUIViewControllerを再利用する
-
22-07-2019 - |
質問
UIViewControllerがあります。これを" FormController"と呼びましょう。 —これは単にオブジェクトを編集するフォームです。 2つの異なる状況で使用したい:
-
新しいオブジェクトの作成-UINavigationControllerの
presentModalViewController:
メソッドを使用して使用します。 -
既存のオブジェクトの編集-ダイアログメソッドを使用せずに、View ControllerをUINavigationControllerスタックにプッシュします。
モーダルの状況では、「キャンセル」のツールバーを使いたいという点でわずかな違いがあります。および「完了」ボタン。ただし、スタックの状況では、UINavigationControllerによって提供されるナビゲーションバーだけが必要です。
これは、「新しい連絡先」が表示される連絡先アプリケーションに似ています。および「連絡先の編集」画面は同じView Controllerを使用しているように見えますが、編集画面がナビゲーションスタックにプッシュされている間、新しい連絡先フォームがモーダルに表示されます。
私の質問は次のとおりです。2つの別個の、しかしほとんど同一のView Controllerを作成せずに両方の状況を処理する最良の方法は何ですか?
" ModalFormController"の作成について考えました。裸の" FormController"をカプセル化します。構成を通じてツールバーを追加しますが、ドキュメントのどこかで、AppleがView Controllerをネストすることを推奨していないことを読みました。
解決
私が(時々)することは、View Controllerのタイプを指定する enum
をセットアップすることです。
たとえば、 Edit
タイプと Add
(" new")タイプの2つのタイプがあります。
Add
タイプはモーダルビューコントローラーを介して実装され、 Edit
タイプは既存のナビゲーションスタックにプッシュされます。
View Controllerの -viewDidLoad:
メソッドで、上記で指定した型の列挙に応じてタイトルやその他の外観特性を設定する switch / case
ツリーを作成します。
これの良いところは、新しいタイプを簡単に追加できることです。欠点は、この列挙を処理するための条件ツリーが、型の違いによってはすぐに複雑になる可能性があることです。
ただし、 switch / case
ツリーを使用すると、管理がはるかに簡単になります。
そのため、2つのタイプで何をしようとしているかによって異なります。しかし、それは間違いなく実行可能です。
他のヒント
サブクラス化を使用しないのはなぜですか? ModalCreateFormController
を EditFormController
のサブクラスにし、サブクラス内のモーダル固有のものを処理します。
View Controllerに明示的なプロパティを設定することに加えて(Alex Reynoldsが示唆しているように)、私には2つのアプローチがあります:
-
何らかの種類のモデルオブジェクトを編集している場合は、現在の状態を問い合わせてください。保存されている場合は、編集モードになっています。それ以外の場合は、作成モードになります。
-
コントローラの
parentViewController
プロパティの値を見てください。UINavigationController
のインスタンスである場合、ナビゲーションスタックにいます。モーダルで表示されている場合は、リストコントローラーのインスタンスになります。
たとえば、余分なivarは嫌いです。
代わりにこれを使用します:
if([[self.navigationController viewControllers] objectAtIndex:0] == self){
//Modal
}else{
//Pushed
}
ちょっとしたハックですが、問題のあるView Controllerがスタックの最初の場合、戻れないというロジックを使用しています。実際には、モーダルで表示されるかどうかの事実を無視しています。
アプリでこれを何回もしなければなりませんでした。モーダルサブクラスを含むさまざまな方法を試してみました& forwardInvocationを使用した再利用可能なモーダルヘルパークラス。最良のパターンは、presentModalViewControllerで使用する呼び出し元のUINavigationControllerを(通常)作成して返すビューコントローラーごとに、containingModalViewControllerメソッドを作成することです。
ほとんどの場合、このメソッドは、ルートビューコントローラーとしてselfを使用してUINavigationControllerを作成して返します(self.navigationControllerをチェックし、nilでない場合は代わりにそれを返すメソッドを繰り返し呼び出します)。他のケースでは、最初にダミーのルートコントローラを作成し、戻るボタンを取得するために2番目に自分自身を押しました。次に、戻るボタンが押されるのを防ぐために、トリックを使用できます。 http:// smallduck .wordpress.com / 2010/10/05 / intercepting-uinavigationcontroller /
場合によっては、ビューにナビゲーションバーが必要ないため、このメソッドはいくつかのフラグを調整してselfを返します。ナビゲーションバーが必要な場合もありましたが、そのメソッドでself.viewを呼び出してから、ビュー階層を微調整してUINavigationBarを追加し、再びselfを返す方が簡単でした。しかし、いずれにせよ、セットアップは多くの場合その1つのメソッドに分離され、呼び出し元はそれぞれのケースで同じように処理します。
Appleは、連絡先アプリケーションが内部でどのように機能するかを説明します:
コンテンツの表示と編集の両方にカスタムView Controllerクラスを使用できるようにするには、
setEditing:animated:
メソッドをオーバーライドします。
一部の機能は無料で利用できます。 編集/完了
ボタン。