8

假设我有一个自定义容器视图控制器 (MainViewController),我在其中执行以下操作:

- (void)viewDidLoad
{
    [super viewDidLoad];        

    HomeViewController *homeVC = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil];
    [self addChildViewController:homeVC];
    [self.view addSubview:homeVC.view];

}

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

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

显然,我可以给 HomeViewController 一个 MainViewController 类型的属性并以这种方式进行调用,但我希望容器视图控制器 API 有一种更简洁的方式。

4

3 回答 3

15

您可以使用委托或阻止;

使用委托

创建协议:

@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 中的按钮时,只需调用:

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 中的按钮时,只需调用:

self.block();
于 2013-02-19T22:19:22.960 回答
10

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

MainViewController为您要执行的操作定义方法...

- (void)someMethod:(BOOL)someParam;

然后在HomeViewController你可以做...

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

HTH :)

于 2013-08-24T16:43:05.677 回答
5

这是一种非常常见的模式。protocol通过提供一个和一个默认扩展,父级将是处理操作的实际实例。

在斯威夫特 3 中:

父视图控制器:

protocol SomeProtocol {
    func foo()
}

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

子视图控制器:

 @IBAction func tapGo(_ sender: Any) {
    (parent as? SomeProtocol)?.foo()
 }
于 2017-02-16T08:24:11.740 回答