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