Setting up an Objective-C delegate for the iPhone SDK
Once Ben Gottlieb of Standalone helped me get past the problem of creating and displaying my main view controller class, I set out to figure out how to do an Objective-C delegate. Unfortunately, none of the examples or tutorials I could find on the internet had a simple, straightforward explanation of what I needed to do to get it working.
After much trial and error, and reading up on as many descriptions on delegates that I could find, I got it working. Here are the steps that I had to go through in my code to get it working:
In my view subclass header file, this line was added to the top:
@protocol KeyboardViewDelegate; |
This line was added to the class definition in the subclass header file:
id <KeyboardViewDelegate> delegate; |
This line was added to the property definitions in the subclass header file:
@property (nonatomic, assign) id delegate; |
And this section was added to the bottom of the subclass header file:
@protocol KeyboardViewDelegate<NSObject> - (void) keyPressHandler:(int)keyPress; @end |
In my view subclass implementation file, this synthesize was added near the top:
@synthesize delegate; |
And this section was added to the method in the subclass view that is wired up (via Interface Builder) to be called when a button is pressed on the view:
if(delegate && [delegate respondsToSelector:@selector(keyPressHandler:)]) { [delegate keyPressHandler:key]; } |
In the view controller header file, of course the view subclass header needs to be included:
#import "KeyboardView.h" |
I had to add the delegate name as part of the interface definition in the view controller header, adding the delegate name in angle brackets, changing it to look like this:
@interface MainViewController : UIViewController <KeyboardViewDelegate> { |
And at the bottom of the view controller header file, I added a definition for the method that matches up with the one from the keyboard view:
- (void) keyPressHandler:(int)keyPress; |
In the view controller implementation file, again the view header subclass needs to be included:
#import "KeyboardView.h" |
In the viewDidLoad method of the view controller, during the creation of the view subclass, I had to set the subclass delegate to be the view controller:
CGRect sizeRect = CGRectMake(0, 225, 320, 190); KeyboardView *view = [[KeyboardView alloc] init]; view.view.frame = sizeRect; [view setDelegate:self]; // this line is pretty important !!! [self.view addSubview:view.view]; |
And at the bottom of the view controller implementation file, thie method defined above is added:
- (void) keyPressHandler:(int)keyPress; { NSLog(@"keyPressHandler just fired"); // do something here } |
And that is it! When running in the simulator, the method in the view controller is fired whenever the method in the view subclass is fired.
Oh, and by the way, I am using a UIPageControl on my view controller, and I found out that, for some reason, I had to go into the viewDidLoad method and add the following line:
pageControl.backgroundColor = [UIColor grayColor]; |
If I did not add this line, the page control would never be visible, even though it was working, as when I tapped on either side of it, the code associated with it fired correctly. The background color of the page control was set to gray in Interface Builder. Anyone have any ideas why that would be?
I think you’re forgetting to include the property definition for delegate, which would be:
@property(assign) id delegate;
Right? Still working through the tutorial, but I couldn’t successfully compile without defining the property for delegate.
Otherwise, this is a great tutorial.
Dana: Good catch, I forgot to put that line in the posting. I have edited the posting to include the line (in which I included nonatomic, not sure if that is needed or not), as well as some other minor edits. Thanks for checking it out. BP
Thanks, this was exactly what I needed to make my fragmented understanding of delegates whole.
One more possible omission; did you forget to include the implementation of the KeyBoardViewDelegate protocol within your ViewController class:
@interface TutorialViewController : UIViewController {
}
I get “______ class does not implement the ______ protocol” compiler warnings and run-time crashes if I don’t include in the class definition.
Thanks again.
Whoops, the website thought I was trying to do html formatting and made some of my text disappear. That line of code should look like:
@interface TutorialViewController : UIViewController *KeyBoardViewDelegate* {
}
Except that the KeyBoardViewDelegate implementation has angle brackets around it rather than asterisks.
Dana: You are right again, I forgot the item. I have edited the posting again, thanks. BP
Thanks for this – has been a great help.
Thanks a lot. This really did help because this is a simple straightforward explanation!
Wooohhhhooooo!
Great tutorial!!! Keep on the great work!
Super tutorial!
Good work.
Great tutorial. Better than anything on the apple website or anywhere else I looked. Thanks a lot!
This helped me a lot!! I’ve been scratching my head at other online tutorial for the past couple days. This just cleared it right up!
Thanks again!
Denis.
Tks a LOT!!
Great step by step information,save me a lot of time!
This is best explanation.
[…] to send message back and forth between classes for years. (And in fact, I did a blog post on Setting up an Objective-C delegate for the iPhone SDK a few years back on this very subject.) Indeed, delegates are a critical part of the Objective-C […]