繁体   English   中英

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

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

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

从vc2中我怎样才能访问vc1?

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

您可以在Vc1中使用prepareForSegue方法,因为当ContainerViewController成为子级时会发生嵌入segue。 您可以将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;
    }
}

编辑:次要代码修复

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

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

    //Use parent
}

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

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

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

您可以使用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
    }
}

使用属性parentViewController作为self.parentViewController

谢谢Bonnie告诉我该怎么做。 事实上,准备segue方法是要走的路。

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

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

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

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

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

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

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

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

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

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

Swift - 另一种方法是在父UIViewController(vc1)中创建一个引用到子/子视图UIViewController(vc2)和vc2到vc1。 在下面的父(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";
          }
      } 

在Storyboard中记得在Identity Inspector中将父UIViewContoller类设置为vc1,将子UIViewContoller类设置为vc2。 按Ctrl +从vc1 UIViewController中的Container View拖动到vc2 UIViewController并选择Embed。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM