Re: [iPhone] Why can't a UITextField be its own delegate?
Re: [iPhone] Why can't a UITextField be its own delegate?
- Subject: Re: [iPhone] Why can't a UITextField be its own delegate?
- From: WT <email@hidden>
- Date: Sun, 26 Jul 2009 02:35:54 +0200
On Jul 26, 2009, at 1:18 AM, WT wrote:
On Jul 26, 2009, at 1:04 AM, WT wrote:
Now, I agree that UITextField will run into an infinite loop (in
the sample app) when calling -respondsToSelector on its delegate
because it is its own delegate. However, why is it then that -
textFieldShouldBeginEditing returns successfully and -
textFieldDidBeginEditing executes but doesn't return? Both of them
successfully print their method names:
- (BOOL) textFieldShouldBeginEditing: (UITextField*) text_field
{
NSLog(@"-textFieldShouldBeginEditing:");
return YES;
}
- (void) textFieldDidBeginEditing: (UITextField*) text_field
{
NSLog(@"-textFieldDidBeginEditing:");
}
It would seem that -respondsToSelector: is not being called at all.
Actually, it is and I do get an infinite loop, thanks to
- (BOOL) respondsToSelector: (SEL) selector
{
NSLog(@"-respondsToSelector:");
return [super respondsToSelector: selector];
}
How do I get a string for the name of the method represented by the
selector?
I'm beginning to understand the intricacies of this problem... First,
since I don't know how to get the name of a method (as a string) from
its selector, I'm simply outputting the selector itself, which is an
address. Now, consider this as the subclass implementation:
#import "CustomTextField.h"
@implementation CustomTextField
- (void) awakeFromNib
{
super.delegate = self;
super.text = @"Hello world";
NSLog(@"awakeFromNib called - delegate set to self");
}
//
=
=
=
=
===================================================================== //
- (BOOL) textField: (UITextField*) text_field
shouldChangeCharactersInRange: (NSRange) range
replacementString: (NSString*) string
{
NSLog(@"-textField: shouldChangeCharactersInRange:
replacementString: %p",
@selector(textField: shouldChangeCharactersInRange:
replacementString:));
return YES;
}
//
=
=
=
=
===================================================================== //
- (BOOL) textFieldShouldBeginEditing: (UITextField*) text_field
{
NSLog(@"-textFieldShouldBeginEditing: %p",
@selector(textFieldShouldBeginEditing:));
return YES;
}
//
=
=
=
=
===================================================================== //
- (void) textFieldDidBeginEditing: (UITextField*) text_field
{
NSLog(@"-textFieldDidBeginEditing: %p",
@selector(textFieldDidBeginEditing:));
}
//
=
=
=
=
===================================================================== //
- (BOOL) textFieldShouldEndEditing: (UITextField*) text_field
{
NSLog(@"-textFieldShouldEndEditing: %p",
@selector(textFieldShouldEndEditing:));
return YES;
}
//
=
=
=
=
===================================================================== //
- (void) textFieldDidEndEditing: (UITextField*) text_field
{
NSLog(@"-textFieldDidEndEditing: %p",
@selector(textFieldDidEndEditing:));
}
//
=
=
=
=
===================================================================== //
- (BOOL) textFieldShouldClear: (UITextField*) text_field
{
NSLog(@"-textFieldShouldClear: %p",
@selector(textFieldShouldClear:));
return YES;
}
//
=
=
=
=
===================================================================== //
- (BOOL) textFieldShouldReturn: (UITextField*) text_field
{
NSLog(@"-textFieldShouldReturn: %p",
@selector(textFieldShouldReturn:));
[self resignFirstResponder];
return YES;
}
//
=
=
=
=
===================================================================== //
- (BOOL) respondsToSelector: (SEL) selector
{
NSLog(@"-respondsToSelector: %p", selector);
if (selector ==
@selector(textField:shouldChangeCharactersInRange:replacementString:) ||
selector == @selector(textFieldShouldBeginEditing:) ||
selector == @selector(textFieldDidBeginEditing:) ||
selector == @selector(textFieldShouldEndEditing:) ||
selector == @selector(textFieldDidEndEditing:) ||
selector == @selector(textFieldShouldClear:) ||
selector == @selector(textFieldShouldReturn:))
{ return YES; }
else
{
return [UITextField instancesRespondToSelector: selector];
}
}
//
=
=
=
=
===================================================================== //
@end
This still causes an infinite loop, with the result being something
like this:
-respondsToSelector: 0x93147998
-respondsToSelector: 0x9316a1b4
-respondsToSelector: 0x931bf364
-respondsToSelector: 0x931389bc
-respondsToSelector: 0x93142b98
-respondsToSelector: 0x931d30c4
-respondsToSelector: 0x93167564
-respondsToSelector: 0x319b8c98
-respondsToSelector: 0x319cc41a
-respondsToSelector: 0x319f4af4
awakeFromNib called - delegate set to self
-respondsToSelector: 0x319b5a68
-textFieldShouldBeginEditing: 0x319b5a68
-respondsToSelector: 0x319aa222
-respondsToSelector: 0x319aa124
-respondsToSelector: 0x319aa100
-respondsToSelector: 0x319aa387
-respondsToSelector: 0x319c9f98
-respondsToSelector: 0x319f4af4
-respondsToSelector: 0x319f4af4
-respondsToSelector: 0x319f4af4
-respondsToSelector: 0x319f4af4
-respondsToSelector: 0x319aa25c
-respondsToSelector: 0x319aade0
-respondsToSelector: 0x319f55a4
-textFieldDidBeginEditing: 0x319f55a4
-respondsToSelector: 0x319c9f98
-respondsToSelector: 0x319f4af4
-respondsToSelector: 0x319c9f98
-respondsToSelector: 0x319f4af4
-respondsToSelector: 0x319b8c98
-respondsToSelector: 0x319cc41a
-respondsToSelector: 0x319f4af4
-respondsToSelector: 0x319caae2
-respondsToSelector: 0x319caae2
-respondsToSelector: 0x319caae2
-respondsToSelector: 0x319caae2
...
So, even though it's responding correctly to the text field delegate
methods, it's recursing infinitely when calling -respondsToSelector
with the selector at address 0x319caae2. The reason it's doing that is
what Kyle already pointed out: the delegate pattern is such that when -
respondsToSelector: returns NO, the delegate is queried, also with a
call to -respondsToSelector. In this case, the text field is its own
delegate, hence the infinite loop.
Naturally, replacing the code inside the else block to return NO is
the wrong thing to do because then (a) it would still loop and (b) it
would be returning NO for *all* delegate methods other than those in
the UITextFieldDelegate protocol. Replacing the code there to return
YES is also wrong since some delegate methods might not be implemented
and the app would crash.
It seems I'll have to opt for having a regular UITextField and a
custom class whose sole purpose is to provide a delegate that does the
common work. As Kyle suggested, I may need to make that a superclass
and derive additional delegates to perform extra work after the common
task.
It's a shame... I would have preferred the solution I had in mind,
because - to me - that's a very clean solution. Too bad it doesn't work.
Thanks to all who pitched in and to Kyle in particular, for nailing
the issue for me.
Wagner
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden