容器视图控制器 – 通知父母的行动

说我有一个自定义的容器视图控制器(MainViewController),我做这样的事情:

- (void)viewDidLoad { [super viewDidLoad]; HomeViewController *homeVC = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil]; [self addChildViewController:homeVC]; [self.view addSubview:homeVC.view]; } 

HomeViewController会有一个button,比如“go”,按下的时候需要前进到下一个视图控制器。 所以我需要通知这个动作的MainViewController。 做这个的最好方式是什么?

我正在使用自定义容器,因为我需要在视图控制器之间进行自定义转换。 当按下“go”时,HomeViewController上的一些视图将animation,而来自新视图控制器的视图将animation到位。

很明显,我可以给HomeViewControllertypes的MainViewController的属性,并通过这种方式进行调用,但我希望有一个更清洁的方式与容器视图控制器API。

您可以使用委托或阻止;

使用委托

创build一个协议:

 @protocol SomeProtocol <NSObject> - (void)someAction; @end 

只需在HomeViewController.h中声明一个委托就可以了:

 id<SomeProtocol> delegate; 

然后在MainViewController的viewDidLoad中像这样设置它:

 homeVC.delegate = self; //some where in MainViewController implement the protocol method -(void)someAction { //do something } 

那么当你按下homeVC中的button时,只需简单地调用:

 if ([self.delegate respondsToSelector:@selector(someAction)]) { [self.delegate someAction]; } 

使用块

在HomeViewController.h中声明一个块属性:

 typedef void (^ActionBlock)(); @property (nonatomic, copy) ActionBlock block; 

然后在MainViewController的ViewDidLoad中:

 homeVC.block = ^(){ //do something }; 

那么当你按下homeVC中的button时,只需简单地调用:

 self.block(); 

还有另一种方法…每个视图控制器都有一个parentViewController属性,所以使用你可以做到这一点…

MainViewController为你想要执行的动作定义一个方法…

 - (void)someMethod:(BOOL)someParam; 

然后在HomeViewController你可以做…

 MainViewController* parent = (MainViewController*)[self parentViewController]; [parent someMethod:paramValue]; 

HTH 🙂

这是一个非常普遍的模式。 通过提供一个protocol和一个默认的扩展名 ,父代将是将要处理这个操作的实际实例。

在Swift 3:

父视图控制器:

 protocol SomeProtocol { func foo() } extension ParentViewController: SomeProtocol { func foo() { // Parent handles it } } 

子视图控制器:

  @IBAction func tapGo(_ sender: Any) { (parent as? SomeProtocol)?.foo() }