ios 从容器视图中的视图控制器中,您如何访问包含容器的视图控制器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21255392/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:12:04  来源:igfitidea点击:

From within a view controller in a container view, how do you access the view controller containing the container?

iosipadviewstoryboardcontainers

提问by Mark Bridges

This is tricky to word but I have a view controller (vc1) that contains a container view (I'm using storyboards). Within that container view is a navigation controller and a root view controller (vc2).

这很难说,但我有一个包含容器视图的视图控制器(vc1)(我正在使用故事板)。在该容器视图中是一个导航控制器和一个根视图控制器 (vc2)。

From within the vc2 how can I get access to vc1?

从 vc2 内部如何访问 vc1?

Or, how do I pass vc1 to vc2? (baring in mind that I'm using storyboards).

或者,我如何将 vc1 传递给 vc2?(请记住,我正在使用故事板)。

采纳答案by Bonnie

You can use the prepareForSeguemethod in Vc1 as an embed segue occurs when the ContainerViewController is made a child. you can pass self as an obj or store a reference to the child for later use.

您可以使用prepareForSegueVc1 中的 方法,因为当 ContainerViewController 成为子项时会发生嵌入转场。您可以将 self 作为 obj 传递或存储对 child 的引用以供以后使用。

- (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;
    }
}

Edit: minor code fix

编辑:次要代码修复

回答by Firula

To access parent view controller from within your child view controller you must override didMoveToParentViewController:

要从子视图控制器中访问父视图控制器,您必须覆盖didMoveToParentViewController

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

    //Use parent
}

On Xcode Command+Click over this method for more info:

在 Xcode Command+单击此方法以获取更多信息:

These two methods are public for container subclasses to call when transitioning between child controllers. If they are overridden, the overrides should ensure to call the super. The parent argument in both of these methods is nil when a child is being removed from its parent; otherwise it is equal to the new parent view controller.

addChildViewController: will call [child willMoveToParentViewController:self] before adding the child. However, it will not call didMoveToParentViewController:. It is expected that a container view controller subclass will make this call after a transition to the new child has completed or, in the case of no transition, immediately after the call to addChildViewController:. Similarly removeFromParentViewController: does not call [self willMoveToParentViewController:nil] before removing the child. This is also the responsibilty of the container subclass. Container subclasses will typically define a method that transitions to a new child by first calling addChildViewController:, then executing a transition which will add the new child's view into the view hierarchy of its parent, and finally will call didMoveToParentViewController:. Similarly, subclasses will typically define a method that removes a child in the reverse manner by first calling [child willMoveToParentViewController:nil].

这两个方法是公共的,供容器子类在子控制器之间转换时调用。如果它们被覆盖,覆盖应该确保调用超级。当子项从其父项中删除时,这两种方法中的 parent 参数都为零;否则它等于新的父视图控制器。

addChildViewController: 将在添加孩子之前调用 [child willMoveToParentViewController:self]。但是,它不会调用 didMoveToParentViewController:。预计容器视图控制器子类将在完成到新子级的转换后进行此调用,或者在没有转换的情况下,在调用 addChildViewController: 后立即调用。同样 removeFromParentViewController: 在移除孩子之前不会调用 [self willMoveToParentViewController:nil]。这也是容器子类的职责。容器子类通常会通过首先调用 addChildViewController: 来定义一个转换到新子级的方法,然后执行一个转换,将新子级的视图添加到其父级的视图层次结构中,最后会调用 didMoveToParentViewController:。类似地,子类通常会通过首先调用 [child willMoveToParentViewController:nil] 以相反的方式定义一个删除子类的方法。

回答by osrl

You can use delegation using the same method Bonnie used. Here is how you do it:

您可以使用 Bonnie 使用的相同方法使用委托。这是你如何做到的:

In your containerViews ViewController:

在您的 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()
}

In your parent ViewController:

在您的父 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
    }
}

回答by Borzh

Use property parentViewControlleras self.parentViewController

使用属性parentViewController作为self.parentViewController

回答by Mark Bridges

Thank you Bonnie for telling me what to do. Indeed the prepare for segue method is the way to go.

谢谢邦妮告诉我该怎么做。事实上,准备转场方法是要走的路。

I'm just clarifying the code and steps here.

我只是在这里澄清代码和步骤。

So first off, name the segue(link) in the storyboard that connects the container view to its first view controller. I named mine "toContainer".

因此,首先,将故事板中的 segue(link) 命名为将容器视图连接到其第一个视图控制器。我将我的命名为“toContainer”。

Then in the view controller containing the container view add this method

然后在包含容器视图的视图控制器中添加此方法

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

So vc2 was the controller I wanted to get reference to.

所以 vc2 是我想要参考的控制器。

This worked for me, your method would be slightly different inside the prepareForSegue if your first viewconroller wasn't a navigation controller.

这对我有用,如果您的第一个 viewconroller 不是导航控制器,您的方法在 prepareForSegue 中会略有不同。

回答by smileBot

1) on VC2 expose a property for passing in a reference to VC1

1) 在 VC2 上公开一个用于传递对 VC1 的引用的属性

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

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

2) on VC1, pass self into the property exposed in VC2 in your prepareForSegue method after you setup your segue's identifier to "ToVC2". Then pass the reference like so:

2) 在 VC1 上,将 segue 的标识符设置为“ToVC2”后,将 self 传递到 prepareForSegue 方法中在 VC2 中公开的属性。然后像这样传递引用:

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

回答by Matt

Swift - An alternative is to create a reference in parent UIViewController (vc1) to child/subview UIViewController (vc2) and in vc2 to vc1. Assign the references in parent(vc1) viewDidLoad() example below.

Swift - 另一种方法是在父 UIViewController (vc1) 中创建对子/子视图 UIViewController (vc2) 和在 vc2 中到 vc1 的引用。在下面的 parent(vc1) viewDidLoad() 示例中分配引用。

Parent UIViewController vc1:

父 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
           }
      }

Child UIViewController vc2:

子 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";
          }
      } 

In the Storyboard remember to set in Identity Inspector the parent UIViewContoller class to vc1 and child UIViewContoller class to vc2. Ctrl+drag from Container View in vc1 UIViewController to vc2 UIViewController and select Embed.

在 Storyboard 中,记得在 Identity Inspector 中将父 UIViewContoller 类设置为 vc1,将子 UIViewContoller 类设置为 vc2。Ctrl+从 vc1 UIViewController 中的容器视图拖动到 vc2 UIViewController 并选择嵌入。