Alexey Borozdin
Alexey Borozdin

Reputation: 19

event delegation

I have two uiviewcontroller: MainViewController and SecondaryViewControlle. In MainViewController I do:

[self.view addSubView:SecondaryViewControlle.view];

The SecondaryViewController is a button by pressing the function to be performed by a MainViewController. How to do?

Upvotes: 0

Views: 67

Answers (2)

user352891
user352891

Reputation: 1191

Option A
It's quicker, and easier, but lacks the maintainability, since there is no contract stating that SecondaryViewController needs to bother calling anything, and self.parentViewController could be any UIViewController.

Option B
The delegate pattern; this is my preference, it's obvious what's happening, what's required, and there's a nice solid contract that states, if you want to initialise me, give me a delegate.

Option C
If SecondaryViewController has to notify multiple objects, it would be quick to use the NSNotificationCenter, but as with Option A, there's no contract, should you need to notify many objects, you would need to remember to listen for notifications on those objects - since this is not the question, I won't go into detail, it's just here for the information

Option A
Within MainViewController.m, do something like so:

SecondaryViewController *viewcontroller = [[SecondaryViewController alloc] initWithNibName:@"SecondaryView" bundle:nil];
[self addChildViewController:viewcontroller];

//set viewcontroller.view frame

[self.view addSubview:viewcontroller.view];

[viewcontroller didMoveToParentViewController:self];

Inside MainViewController.h

-(void) performButtonClickAction;

Inside MainViewController.m:

-(void) performButtonClickAction {
    //Do something constructive
}

and then inside the SecondaryViewController.m:

-(IBAction) buttonPressed:(id) sender {
    [self.parentViewController performButtonClickAction];
}

Option B
Inside SecondaryViewController.h

@protocol SecondaryViewControllerDelegate <NSObject>
-(void) eventAFromViewController:(UIViewController *) viewController;
-(void) eventBFromViewController:(UIViewController *) viewController;
@end

@interface SecondaryViewController : UIViewController {
    id<SecondaryViewControllerDelegate> delegate;
}

@property (assign, nonatomic)    id<SecondaryViewControllerDelegate> delegate;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<SecondaryViewControllerDelegate>) theDelegate;
@end

Inside SecondaryViewController.m @synthesize delegate = _delegate;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<SecondaryViewControllerDelegate>) theDelegate
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.delegate = theDelegate;
    }
    return self;
}

-(IBAction) buttonPressed:(id) sender {
    if( self.delegate != nil ) {
        [_delegate eventAFromViewController:self];
    }
    else {
        //No delegate
    }
}

Upvotes: 0

Michael Dautermann
Michael Dautermann

Reputation: 89509

You'd start by defining a protocol in your SecondViewControlle.h file, something like:

@protocol SecondViewControlleDelegate

- (void) doSomething

@end

You would also need to add a "delegate" ivar to your SecondViewControlle .h file. It would be the delegate line:

@interface SecondViewControlle : UIViewController

...
...
...

@property (nonatomic, assign) id delegate; // all you need to do is add this line inside your interface declarations

...
...
...
@end 

Then, when you create / instantiate your SecondaryViewControlle from your MainViewController, make certain to add the MainViewController as the delegate like so:

SecondaryViewControlle.delegate = self;
[self.view addSubView:SecondaryViewControlle.view];

Now the "delegate" of your SecondaryViewControlle view controller points back to your MainViewController.

And when the button is pressed, you can simply do something like:

- (IBAction) buttonIsPressed: (id) sender
{
    [delegate doSomething];
}

Now, I need to give you some advice here.

1 ) DO NOT use the class names as object names. Instead of having an object named "SecondViewControlle", name it something different (and start it with a lower case, which is Objective-C convention), something like "moreDetailVC".

2) I've told you how to do this with a delegate pattern, but this may not be the most appropriate way to do whatever it is that you're trying to do. After all, the MainViewController object (which should be renamed mainVC to differentiate the object from the class) is not on screen or visible so maybe there's a better place to put the functionality?

Upvotes: 1

Related Questions