iOS6では、新しいコンテナビューに気づきましたが、含まれているビューからそのコントローラにアクセスする方法がよくわかりません。
シナリオ:
コンテナビューを格納するビューコントローラからアラートビューコントローラのラベルにアクセスしたい。
それらの間にセグエがあります、私はそれを使うことができますか?
iOS6では、新しいコンテナビューに気づきましたが、含まれているビューからそのコントローラにアクセスする方法がよくわかりません。
シナリオ:
コンテナビューを格納するビューコントローラからアラートビューコントローラのラベルにアクセスしたい。
それらの間にセグエがあります、私はそれを使うことができますか?
はい、セグエを使用して、子ビューコントローラ(およびそのビューとサブビュー)にアクセスできます。alertview_embed
ストーリーボードの属性インスペクターを使用して、セグエに識別子(など)を付けます。次に、親ビューコントローラー(コンテナービューを格納するコントローラー)に次のようなメソッドを実装させます。
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString * segueName = segue.identifier;
if ([segueName isEqualToString: @"alertview_embed"]) {
AlertViewController * childViewController = (AlertViewController *) [segue destinationViewController];
AlertView * alertView = childViewController.view;
// do something with the AlertView's subviews here...
}
}
これは簡単に行うことができますself.childViewControllers.lastObject
(子供が 1 人しかいない場合、それ以外の場合は を使用しますobjectAtIndex:
)。
スウィフトプログラミング用
あなたはこのように書くことができます
var containerViewController: ExampleViewController?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// you can set this name in 'segue.embed' in storyboard
if segue.identifier == "checkinPopupIdentifierInStoryBoard" {
let connectContainerViewController = segue.destinationViewController as ExampleViewController
containerViewController = connectContainerViewController
}
}
このprepareForSegue
アプローチは機能しますが、セグエ識別子のマジック ストリングに依存しています。たぶんもっと良い方法があります。
目的の VC のクラスがわかっている場合は、計算されたプロパティを使用してこれを非常にうまく行うことができます。
var camperVan: CamperVanViewController? {
return childViewControllers.flatMap({ $0 as? CamperVanViewController }).first
// This works because `flatMap` removes nils
}
これは に依存しchildViewControllers
ます。最初のものに頼るのはもろいかもしれないことに同意しますが、求めるクラスに名前を付けると、これは非常に堅実に見えます。
計算されたプロパティを使用した Swift 3 の更新された回答:
var jobSummaryViewController: JobSummaryViewController {
get {
let ctrl = childViewControllers.first(where: { $0 is JobSummaryViewController })
return ctrl as! JobSummaryViewController
}
}
これは、最初の一致に達するまで子のリストを反復するだけです。
self.childViewControllers
親からの制御が必要な場合は、より関連性があります。たとえば、子コントローラーがテーブル ビューであり、それを強制的にリロードしたり、ボタン タップやその他の親ビュー コントローラーのイベントを介してプロパティを変更したりしたい場合は、prepareForSegue 経由ではなく、ChildViewController のインスタンスにアクセスすることで実行できます。どちらも異なる方法でアプリケーションを持っています。
View Controller のタイプで Swift の switch ステートメントを使用する別の方法があります。
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
switch segue.destination
{
case let aViewController as AViewController:
self.aViewController = aViewController
case let bViewController as BViewController:
self.bViewController = bViewController
default:
return
}
}
私は次のようなコードを使用します:
- (IBAction)showCartItems:(id)sender{
ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:@"ListOfCartItemsViewController"];
[self addChildViewController:listOfItemsVC];
}
誰かがSwift 3.0を探している場合、
viewController1、viewController2などにアクセスできるようになります。
let viewController1 : OneViewController!
let viewController2 : TwoViewController!
// Safety handling of optional String
if let identifier: String = segue.identifier {
switch identifier {
case "segueName1":
viewController1 = segue.destination as! OneViewController
break
case "segueName2":
viewController2 = segue.destination as! TwoViewController
break
// ... More cases can be inserted here ...
default:
// A new segue is added in the storyboard but not yet including in this switch
print("A case missing for segue identifier: \(identifier)")
break
}
} else {
// Either the segue or the identifier is inaccessible
print("WARNING: identifier in segue is not accessible")
}
あなたはこのように書くことができます
- (IBAction)showDetail:(UIButton *)sender {
DetailViewController *detailVc = [self.childViewControllers firstObject];
detailVc.lable.text = sender.titleLabel.text;
}
}