web-dev-qa-db-ja.com

コンテナビューのView Controller内から、コンテナを含むView Controllerにどのようにアクセスしますか?

これはWordにとって扱いにくいですが、コンテナビューを含むView Controller(vc1)があります(ストーリーボードを使用しています)。そのコンテナビュー内には、Navigation ControllerとルートView Controller(vc2)があります。

Vc2内からvc1にアクセスするにはどうすればよいですか?

または、vc1をvc2に渡すにはどうすればよいですか? (私はストーリーボードを使用していることを念頭に置いて)。

51
Mark Bridges

ContainerViewControllerが子になると、埋め込みセグエが発生するため、Vc1でprepareForSeguemethodを使用できます。 selfをobjとして渡すか、後で使用するために子への参照を保存できます。

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSString * segueName = segue.identifier;
    if ([segueName isEqualToString: @"embedseg"]) {
        UINavigationController * navViewController = (UINavigationController *) [segue destinationViewController];
        Vc2 *detail=[navViewController viewControllers][0];
        Vc2.parentController=self;
    }
}

編集:マイナーコード修正

51
Bonnie

子View Controller内から親View Controllerにアクセスするには、didMoveToParentViewControllerをオーバーライドする必要があります。

- (void)didMoveToParentViewController:(UIViewController *)parent {
    [super didMoveToParentViewController:parent];

    //Use parent
}

Xcodeコマンド+詳細については、このメソッドをクリックしてください:

これらの2つのメソッドは、子コントローラー間で移行するときに呼び出すコンテナーサブクラスに対してパブリックです。それらがオーバーライドされる場合、オーバーライドは必ずスーパーを呼び出す必要があります。これらの両方のメソッドの親引数は、子がその親から削除されているときはnilです。それ以外の場合は、新しい親View Controllerと同じです。

addChildViewController:は、子を追加する前に[child willMoveToParentViewController:self]を呼び出します。ただし、didMoveToParentViewController:は呼び出されません。コンテナビューコントローラサブクラスは、新しい子への遷移が完了した後、または遷移がない場合はaddChildViewController:の呼び出しの直後にこの呼び出しを行うことが期待されています。同様に、removeFromParentViewController:は、子を削除する前に[self willMoveToParentViewController:nil]を呼び出しません。これは、コンテナサブクラスの責任でもあります。コンテナサブクラスは通常、最初にaddChildViewController:を呼び出して新しい子に移行するメソッドを定義し、次に新しい子のビューをその親のビュー階層に追加し、最後にdidMoveToParentViewController:を呼び出す移行を実行します。同様に、サブクラスは通常、最初に[child willMoveToParentViewController:nil]を呼び出すことにより、逆の方法で子を削除するメソッドを定義します。

17
Firula

プロパティparentViewControllerself.parentViewControllerとして使用します

10
Borzh

Bonnieが使用したのと同じ方法を使用して、委任を使用できます。方法は次のとおりです。

ContainerViews ViewControllerで:

class ContainerViewViewController: UIViewController {
   //viewDidLoad and other methods

   var delegate: ContainerViewControllerProtocol?

   @IBAction func someButtonTouched(sender: AnyObject) { 
    self.delegate?.someDelegateMethod() //call this anywhere
   }

}

protocol ContainerViewControllerProtocol {
    func someDelegateMethod()
}

親ViewControllerで:

class ParentViewController: UIViewController, ContainerViewControllerProtocol {
   //viewDidLoad and other methods

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "filterEmbedSegue" {
            let containerViewViewController = segue.destinationViewController as ContainerViewViewController

            containerViewViewController.delegate = self
        }
    }

    func someDelegateMethod() {
        //do your thing
    }
}
10
osrl

ボニー、どうしたらいいか教えてくれてありがとう。確かに、セグエ法の準備が進むべき道です。

ここでコードと手順を明確にしています。

最初に、コンテナビューを最初のView Controllerに接続するストーリーボードのsegue(link)という名前を付けます。私は「toContainer」という名前を付けました。

次に、コンテナビューを含むView Controllerでこのメソッドを追加します

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString: @"toContainer"]) {
        UINavigationController *navViewController = (UINavigationController *) [segue destinationViewController];
        UIViewController *vc2 = [navViewController viewControllers][0];
    }
}

そのため、vc2は参照したいコントローラーでした。

これは私にとってはうまくいきました。最初のviewconrollerがNavigation Controllerでない場合、メソッドはprepareForSegue内でわずかに異なります。

2
Mark Bridges

1)VC2で、VC1への参照を渡すためのプロパティを公開します

//VC2.h
#import "VC1.h"

@interface VC2 : NSObject
@property (strong, nonatomic) VC1 *parent;
@end

2)VC1で、セグエの識別子を「ToVC2」に設定した後、prepareForSegueメソッドでVC2で公開されているプロパティにselfを渡します。次に、参照を次のように渡します。

//VC1.m
@implementation VC1 
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:@"ToVC2"]) {
    VC2 *vc2 = segue.destinationViewController;
    vc2.parent = self;
}
}
1
smileBot

Swift-別の方法は、親UIViewController(vc1)から子/サブビューUIViewController(vc2)への参照と、vc2からvc1への参照を作成することです。以下のparent(vc1)viewDidLoad()の例で参照を割り当てます。

親UIViewController vc1:

      class vc1: UIViewController {

          @IBOutlet weak var parentLabel: UILabel!
          var childVc2: vc2?;

           overide func viewDidLoad() {
               super.viewDidLoad();
               // Use childViewControllers[0] without type/class verification only 
               // when adding a single child UIViewController 
               childVc2 = self.childViewControllers[0] as? vc2;
               childVc2?.parentVc1 = self
           }
      }

子UIViewController vc2:

      class vc2: UIViewCortoller {
          var parentVc1: vc1?;

          // At this point child and parent UIViewControllers are loaded and 
          // child views can be accessed
          override func viewWillAppear(_ animated: Bool) {
             parentVc1?.parentLabel.text = "Parent label can be edited from child";
          }
      } 

ストーリーボードで、Identity Inspectorで親UIViewContollerクラスをvc1に、子UIViewContollerクラスをvc2に設定することを忘れないでください。 Ctrl + vc1 UIViewControllerのコンテナビューからvc2 UIViewControllerにドラッグして、[埋め込み]を選択します。

0
Matt