Say I have a custom container view controller (MainViewController) where I do something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
HomeViewController *homeVC = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil];
[self addChildViewController:homeVC];
[self.view addSubview:homeVC.view];
}
The HomeViewController will have a button, such as "go", that when pressed will need to advance to the next view controller. So I need to notify the MainViewController of this action. What is the best way to do this?
I'm using a custom container because I need to do custom transitions between the view controllers. When "go" is pressed, some of the views on the HomeViewController will animate while the views from the new view controller are animating into place.
Obviously I could give the HomeViewController a property of type MainViewController and make calls that way, but I'm hoping that there is a cleaner way with the container view controller API.
You can either use delegate or block;
Using delegate
Create a protocol :
@protocol SomeProtocol <NSObject>
- (void)someAction;
@end
Just declare a delegate in HomeViewController.h like this:
id<SomeProtocol> delegate;
and then in MainViewController's viewDidLoad set it like this:
homeVC.delegate = self;
//some where in MainViewController implement the protocol method
-(void)someAction
{
//do something
}
then when you press the button in homeVC, just simply call:
if ([self.delegate respondsToSelector:@selector(someAction)]) {
[self.delegate someAction];
}
Using Block:
In HomeViewController.h declare a block property:
typedef void (^ActionBlock)();
@property (nonatomic, copy) ActionBlock block;
then in MainViewController ViewDidLoad:
homeVC.block = ^(){
//do something
};
then when you press the button in homeVC, just simply call:
self.block();
There's another way too...
Every view controller has a parentViewController
property so using that you can do this...
In MainViewController
define a method for the action you want to perform...
- (void)someMethod:(BOOL)someParam;
Then in HomeViewController
you can do...
MainViewController* parent = (MainViewController*)[self parentViewController];
[parent someMethod:paramValue];
HTH :)
This is a very common pattern. The parent will be the actual instance that will handle the action, by providing a protocol
and a default extension.
In Swift 3:
Parent view controller:
protocol SomeProtocol {
func foo()
}
extension ParentViewController: SomeProtocol {
func foo() {
// Parent handles it
}
}
Child view controller:
@IBAction func tapGo(_ sender: Any) {
(parent as? SomeProtocol)?.foo()
}
来源:https://stackoverflow.com/questions/14968321/container-view-controllers-notify-parent-of-action