views:

1275

answers:

3

I'm creating a simple project for iPhone, using XCode and Interface Builder. While I understand what a delegate is, I have a problem with using it.

I have an UITextField in my interface. It displays keyboard when user taps on it, but I need to program manually how to hide keyboard. It can be done using delegates. So in IB, I'm taking Object from library, giving it's class name as Control1Delegate and then connecting the delegate outlet from my textfield to be this Control1Delegate. I also have .m and .h files for this Control1Delegate class :

Control1Delegate.h

@interface Control1Delegate : NSObject <UITextFieldDelegate> {
}

- (BOOL) textFieldShouldReturn:(UITextField *)textField;

@end

Control1Delegate.m

#import "Control1Delegate.h"

@implementation Control1Delegate

- (BOOL) textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return YES;
}

@end

But this doesn't work. When running, it just never reaches the textFieldShouldReturn method or crashes without msg or with EXEC_BAD_ACCESS. The funny thing is that when I move the method into controller file (the one wizard has generated) and connect from UITextField to this controller (File's Owner), everything works as expected. I saw that most apple code tutorial puts delegated methods into random objects rather then separate class - I would like to know why. Can't I have delegate in separate class?

What I'm missing here? Some null pointer? Object livecycle?

A: 

You can put delegate methods in any class, including one built just for that purpose. The reason Apple (and other programmers) usually don't make classes specifically for delegate functions is it becomes overly complex and hard to share data. For instance, in one of my projects I might make a Window Controller subclass that handles delegate methods from the window, the table view inside the window, and the window's toolbar. Everything you need to manipulate and maintain the state of that window is in one controller class. Now imagine three separate classes (plus probably a controller class to manage them) doing the same functions-- that's a lot of extra work for no real benefit.

As to why it's crashing, it sounds like you're making a mistake with memory management somewhere else in your application. You can use the debugger to track down exactly where it's coming from.

Marc Charbonneau
Thanks. While I can understand your point and imagine where it's useful, I'm generally against big controller classes with everything in it. I dislike the way of mixing controller methods with delegate methods, separating them with something like : /* delegate methods start from this point */
rattkin
+1  A: 

Your Control1Delegate object is getting destroyed soon after it is created. All top-level Nib objects must be retained if you want to keep them alive. Refer to the Resource Programming Guide: The Nib Object Life Cycle.

The File's Owner could have a property like this, in order to retain the object:

@property (nonatomic, retain) IBOutlet Control1Delegate *control1delegate;

Remember to release the object after it is no longer needed.

Chris Lundie
Thank you so much! I knew I was hitting a nil object, but I couldn't figure out how to retain it. What's missing from this answer, though maybe obvious, is that you have to connect in IB the delegate outlet you've just created with the Delegate Object you have there.
rattkin
A: 

Thank you both. Not only I know now how to solve my problem, but also finally understood how objects are retained in Nib creation process. It's not enough to create object in IB, if it's a new entity, it has to be connected to a real ivar in File's Owner (with properly synthetised getter/setter).

rattkin