容器视图控制器 - 通知父级视图控制器的操作

9

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

- (void)viewDidLoad
{
    [super viewDidLoad];        

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

}

HomeViewController将拥有一个按钮,例如“前进”,当按下时需要转到下一个视图控制器。因此,我需要通知MainViewController执行此操作。最好的方法是什么?
我使用自定义容器,因为我需要在视图控制器之间进行自定义转换。当按下“前进”按钮时,HomeViewController上的某些视图将进行动画,而来自新视图控制器的视图则正在定位。
显然,我可以为HomeViewController提供一个MainViewController类型的属性,并以这种方式进行调用,但我希望有一种更清洁的方法来使用容器视图控制器API。
3个回答

15
你可以使用代理(delegate)或块(block)来实现此功能; 使用代理 创建一个协议(protocol):
@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
}

那么当您在主页视图控制器中按下按钮时,只需简单调用:

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

使用 Block:

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

typedef void (^ActionBlock)();

@property (nonatomic, copy) ActionBlock block;

然后在MainViewController的ViewDidLoad方法中:

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

然后当您在homeVC中按下按钮时,只需简单调用:

self.block();

好的,那么我不能从UIViewController Containment API中获得任何优势吗? - soleil
不太确定,但这篇帖子可能会有所帮助点击这里 - Eric Qian
1
如果可以的话,我会给这个点赞三次。它不仅回答了我的问题,而且让我对块有了十倍的理解 :) - Pedro
1
typedef声明块需要一个类型,例如:typedef void (^ActionBlock)(); - Pedro
@EricQian,当我实现处理子视图操作的块时,我遇到了错误访问错误。我已经在这里发布了我的问题,你能帮我解决吗? - Peer Mohamed Thabib

10

还有另一种方法...每个视图控制器都有一个parentViewController属性,因此可以使用它来执行以下操作...

MainViewController中定义一个方法,用于您要执行的操作...

- (void)someMethod:(BOOL)someParam;

然后在 HomeViewController 中,您可以执行...

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

HTH :)


2
这是一个好的快速而简便的方法。如果你有更多时间来制定协议,可以使用被选中的答案。谢谢,Pedro! - Shaun

5

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

在Swift 3中:

父视图控制器:

protocol SomeProtocol {
    func foo()
}

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

子视图控制器:

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

非常感谢,这正是我所需要的 :) - mic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接