My iPhone application as a main view controller, but it also has another UIView subclass (created in Interface Builder) that is instantiated in code. I wanted this other view to serve as a replacement for the standard on-screen keyboards provided on the iPhone, so it would need to be able to communicate with the main view controller. Ben Gottlieb of Standalone (and others) suggested that I set up delegates to make this happen. That way, I can have the one UIView subclass that I can use over and over again, and I won’t have to do any kind of event wiring up in Interface Builder.
Once Ben helped me get past the problem of creating and displaying the class, I set out to figure out how to do the 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:
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:
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:
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?