I’m programmatically replacing a UITextField with a UITextView, but this seems to break something in Apple’s code.
The class that does the swap-over is the delegate for both. All the delegate methods on the FIELD work correctly – I use “didBeginEditing” to trigger the swap from FIELD -> VIEW.
The didBeginEditing / shouldBeginEditing methods on the VIEW are also invoked correctly.
However … the shouldEndEditing / didEndEditing methods on the VIEW delegate are never invoked. It doesn’t matter how I remove focus, they are never called (I have them breakpointed, with log statements too). e.g. NONE of the following work:
- Tap a different textfield on the screen (FIELD delegate gets “shouldBegin” and “didBegin” – VIEW delegate gets nothing)
- Use a gesture recognizer on a background view to invoke “resignFirstResponder” for each element on screen (if a different field is selected, then FIELD delegate gets “shouldEnd” and “didEnd”. VIEW gets nothing even if it’s selected)
The fact that should/did begin methods are called shows that the delegate has been assigned OK, and is functioning correctly – but why / how are the should/did end methods being ignored? It’s as if Apple has a bug in their code for detecting the existence of those methods.
NB: I used Xcode autocomplete / content-assist to create the methods, so I’m confident there’s no typos. Just to be clear:
-(BOOL)textViewShouldEndEditing:(UITextView *)textView
{
textComments.text = textView.text;
[textView.superview insertSubview:self.textComments aboveSubview:textView];
[textView removeFromSuperview];
return TRUE;
}
-(void)textViewDidEndEditing:(UITextView *)textView
{
textComments.text = textView.text;
[textView.superview insertSubview:self.textComments aboveSubview:textView];
[textView removeFromSuperview];
}
-(BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
NSLog(@"blah" );
return TRUE;
}
-(void)textViewDidBeginEditing:(UITextView *)textView
{
NSLog(@"blah" );
}
I finally found the cause: some 3rd-party code was subscribing to Apple’s keyboard-did-appear/disapper notifications, and removing itself as a listener.
Unfortunately, Apple’s NSNotificationCenter cannot remove a single listener / callback selector – it has to remove all the callbacks of a given instance on a given notification pattern.
So, as a side-effect, this 3rd-party code was removing my callback selector, even though none of my own code removed it. I was setting / resetting delegates in the keyboard notifications. The exact timings that Apple fires-off keyboard appear/disappear methods seems to be slightly different (consistently) for textfields and textviews, and that was why the behaviour only affected one type not the other.
My guess is that Dominic might be seeing a similar problem – and that his call to re-set the delegate “nudges” the timing of some notifications (accidentally), thereby fixing it.