说我有一个自定义的容器视图控制器(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一个更清洁的方式。
您可以使用委托或块;
使用代理
创建一个协议:
@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];
}
使用Block:
在HomeViewController.h声明块属性:
typedef void (^ActionBlock)();
@property (nonatomic, copy) ActionBlock block;
然后在MainViewController viewDidLoad中:
homeVC.block = ^(){
//do something
};
那么当你按下homeVC按钮,只需简单地调用:
self.block();
有太多的另一种方式......每个视图控制器具有parentViewController
因此使用,你可以做这个属性...
在MainViewController
定义要执行的操作的方法...
- (void)someMethod:(BOOL)someParam;
然后在HomeViewController
你可以做...
MainViewController* parent = (MainViewController*)[self parentViewController];
[parent someMethod:paramValue];
HTH :)
这是一个很常见的模式。 家长会的实际情况,将处理的动作,通过提供protocol
和默认的扩展 。
在斯威夫特3:
父视图控制器:
protocol SomeProtocol {
func foo()
}
extension ParentViewController: SomeProtocol {
func foo() {
// Parent handles it
}
}
儿童视图控制器:
@IBAction func tapGo(_ sender: Any) {
(parent as? SomeProtocol)?.foo()
}