Storyboardで子View ControllerをカスタムContainer View Controllerに関連付けることはできますか?
子View ControllerをTab View Controllerにリンクでき、1つのView ControllerをNavigation Controllerにリンクできます。
子VCを受け入れるには、コンテナVCに対して何を行う必要がありますか?
カレブとマットの答えのコンボのようなものとして、私はやった:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"cpdc_check_embed"]) {
self.checkVC = segue.destinationViewController;
}
}
...ここで、checkVC
はコンテナコントローラのプロパティです。
@property (weak,nonatomic) PXPCheckViewController * checkVC;
embed
セグエのStoryboard ID
を必要なものに設定するだけです(この場合、cpdc_check_embed
):
...そして-prepareForSegue:sender:
の識別子を確認します。
まだアウトレットではありませんが、マット(IMHO)よりもクリーンで、カレブよりも具体的です。
ストーリーボードは、組み込みのコンテナービューコントローラーを非常にうまく処理し、セグエを子/ルートビューコントローラーに表示して、関係が明確に表示されるようにします。また、子と親のView Controllerがどのように異なるシーンに分離されるかは素晴らしいことです。
自分のプロジェクトでこの効果を達成したい場合、完璧ではないが非常に簡単なトリックがあります。この例では、「左」と「右」の2つのタブのみを持つTab Bar Controllerのように動作するコンテナビューコントローラがあるとします。親のビューコントローラーを表すシーンがあり、2つの別々のシーンが「左」の子ビューコントローラーと「右」の子ビューコントローラーの両方を表します。
不可能ではありますが、コンテナビューコントローラから異なるシーンの子にIBOutlet
sを作成し、コンテナビューコントローラが表示されたら、親/子関係をルールは IViewController documentation を説明しました。 「左」および「右」の子View Controllerへの参照があれば、問題なく関係を設定できます。
この参照問題の標準的な解決策は、Object
アウトレットをコンテナビューコントローラのシーンにドラッグし、そのクラスタイプを子ビューコントローラクラスのインスタンスとして指定することにより、子ビューコントローラへの参照を作成することです。
ただし、Appleのビルトインコンテナのような異なるシーンで子供を分離するために、別のトリックを使用します。まず、コンテナクラスContainerViewController
で次のプロパティが宣言されているとします。
@property (nonatomic, strong, readwrite) UIViewController *leftViewController;
@property (nonatomic, strong, readwrite) UIViewController *rightViewController;
ストーリーボードで、「左」View Controllerを表すシーンを選択します。属性インスペクターで、View Controllerのidentifier
プロパティを"cvc_leftViewController"
に設定します(「cvc_」はContainerViewController
を指しますが、実際には識別子は任意です)。右側のView Controllerのシーンにも同じことを行い、その識別子を"cvc_rightViewController"
に設定します。
次のコードをContainerViewController
のviewDidLoad
メソッドに挿入します。
if (self.storyboard) {
_leftViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"cvc_leftViewController"];
_rightViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"cvc_rightViewController"];
}
ContainerViewController
がストーリーボードからロードされると、それぞれのシーンから「左」および「右」のビューコントローラーを取得し、そのプロパティを介してそれらへの参照を設定します。子View Controllerインスタンスを制御できるようになったので、親/子関係を好きなように設定できます。適切に行う方法については、 IViewController documentation を参照してください。
このトリックは完璧ではなく、多くの注意事項がありますが、注意すればプロジェクトでうまく機能させることができます。
編集:これは完全に不要で何の意味もありませんが、本当に本当にストーリーボードにコンテナから子ビューへの接続を表示させたい場合Appleのビルトインコンテナと同様に、上記の方法を使用して、コンテナシーンと子シーンの間にセグエを直接設定し、それらのセグエを実行しないでください。これですべてが正常に動作し、きれいになります。
Storyboardで子View ControllerをカスタムContainer View Controllerに関連付けることはできますか?
ここで求めているのは、あるシーンのView Controllerを別のシーンのView Controllerのコンセントに接続する方法だと思います。おそらく、ストーリーボードの機械には、ストーリーボードのすべてのシーンが同時にロードされるわけではないため、それが可能だとは思わない。
あるシーンから次のシーンにセグエするときに、あるView Controllerから別のView Controllerに情報を渡したいので、おそらくこれを求めているでしょう。ストーリーボードで作業しているときにこれを行う方法は、-prepareForSegue:sender:
セグエの影響を受ける一方または両方のView Controller。 segue
パラメーターで提供されるUIStoryboardSegueオブジェクトには、sourceViewController
およびdestinationViewController
プロパティ、およびidentifier
プロパティがあります。これらのプロパティを使用して、View Controller間でデータを転送しようとしているセグエを識別できます。
Ray Wenderlichのブログには、ストーリーボードを使用するのに役立つ素敵な2部構成のチュートリアルがあります。
パート1 ストーリーボードプロジェクトの設定、シーンの追加、セグエの作成について説明します。
パート2 セグエを使用してシーン間を遷移することを処理します(上記のprepareForSeque
メソッドを含む)。
iOS 5では、同じシーンで複数のView Controllerをアクティブにすることができます(ただし、1つは引き続き担当する必要があります)。そのため、ストーリーボードの1つのシーンに複数のコントローラーが含まれる場合があります。アウトレットを使用してこれらのコントローラーを相互に接続し、IBで行ったのと同じ方法でこれらの接続を構成できます。同じシーンでコントローラーから別のコントローラーにドラッグします。通常のコンセントリストが開いて、接続するコンセントを選択できます。
あるシーンで複数のコントローラーを使用するための鍵は、IBのオブジェクトリストにある不思議なオブジェクトを使用して、他のビューコントローラーを表し、そのコンセントを接続することです。
この回答 iOS 5でストーリーボードを使用してカスタムView Controllerコンテナを作成する方法 が役立つと思います。答えは、非常に役立つ実用的なサンプルアプリも提供します。
@Benの(それ以外の場合は合理的な)答えの問題は、ネストの1つのレベルでのみ機能することです。さらに、以降のすべてのVC=をカスタマイズして、prepareForSegueにネストされたView Controllerを保存する必要があります。
これを解決するために、NSObjectベースのインデックスの探索に多くの時間を費やしました。これをストーリーボードに追加し、シーンにバインドすると、グローバルインデックスにその親VCタイプとrestoreIdに基づきます。これは機能します/機能しますが、最終的には手間がかかり、視覚的にバインドし、プログラムで検索するという2段階のプロセスが必要です。
私にとって、最も簡単で最も一般的な解決策は、View Controllerの階層をゆっくりと下降させることです
私の簡単なテストプロジェクトでは、viewDidLoadに次の行を追加しました。
_ self.left.data = [
"Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.",
"De carne lumbering animata corpora quaeritis." ]
_
ここで、left
は次のように定義されます。
_lazy var left:CollectionViewController = { [unowned self] in
return self.childViewControllerWithId("Left") as! CollectionViewController }()
_
childViewControllerWithId
は次のように定義されます:
_extension UIViewController {
func childViewControllerWithId(rid:String) -> UIViewController? {
// check immediate child controllers
for vc in self.childViewControllers as! [UIViewController] {
if vc.restorationIdentifier == rid { return vc }
}
// check nested controllers
for vc in self.childViewControllers as! [UIViewController] {
if let vc = vc.childViewControllerWithId(rid) {
return vc
}
}
assert(false, "check your assumptions")
return nil
}
}
_
必要に応じて、タイプに基づいて他のfind
バリアントを実行できることに注意してください。また、上記の場合、ストーリーボードファイルで復元IDを定義する必要があることに注意してください。同じView Controllerのインスタンスを繰り返していない場合は、typeを使用する方が簡単です。
願わくば明らかなことを述べるために、prepareForSegueを実装する必要も、遅延読み込みを使用する必要もありません。find(...)
を呼び出すだけです。