A question about UITextView delegate methods....

Hi,

I have a question about a weird behaviour in my app. I have a UITextView in one of the views. ts ViewController is degignated as the delegate for <UITextViewDelegate>.

When the editing action is triggered (by touching the text on the sceen), the textViewShouldBeginEditing and textViewDidBeginEditing are not called. I have breakpoints there and they are not hit.

However - textViewShouldEndEditing and textViewDidEndEditing - are called when the save or cancel button is touched.

Here are the code snippets:

EditView.h:
@interface EditView : UIView <UITextViewDelegate> {
.
.
UITextView *theNote;
.
}

EditView.m:
-(IBAction) editAction:(id)sender {
theNote.editable = YES; // -----> until this action, the text is not editable.
theNote.delegate = self;
theNote.returnKeyType = UIReturnKeyDefault;
theNote.keyboardType = UIKeyboardTypeDefault;
}

The four delegate methods follow later in this file.



Am I missing something or doing something incorrectly?

Thanks, Sam.

iMac, Mac OS X (10.5.5)

Posted on Aug 15, 2009 7:41 PM

Reply
10 replies

Aug 15, 2009 9:29 PM in response to K T

Hi KT

I am not sure that I understand the quote!

From what I understand of the delegate methods, they are to give the app some control of action when the editing-related events occur, right? Besides the method I mentioned in the base message, I have the delegate methods in my app. I want to use these methods to cover the text-editing chores of the app - but if the delegate method is not called, some of the chores can't be done.

I am new at app-development and therefore need some understanding of why this is happening, and what I can do to correct the problem.

Sam.

Aug 15, 2009 10:36 PM in response to Shnaps

welcome to the fuzzy world of the iPhont libraries. Unfortunately one can never tell which event stream one should be getting, because many of the standard handlers absorb events and they are swallowed up and never seen by your code. This is the black hole of both the Microsoft OS and iPhone, no actual documentation on what event streams are guaranteed, in what order or quantity. Makes program a trial and error time waster instead of a thinking game like chess.

Aug 15, 2009 11:40 PM in response to Shnaps

Shnaps wrote:
textViewShouldBeginEditing and textViewDidBeginEditing are not called.

Hey Sam - I made a testbed from the View-Based App template, adding only a text view and a button to send resignFirstResponder. I'm getting all the expected delegate messages. The only anomaly is that the ShouldBegin and ShouldEndEditing methods are being called more than once, often 3 times, though never more than that.

I need to add that I'm testing on 2.1 right now, but I doubt we're looking at a 3.0 problem. There's not a peep about a similar problem on the web, so I'm guessing my results are relevant. When a delegate method is ignored, I always check for a spelling error in the signature. All the text view delegate methods are optional so the compiler won't warn you about missing methods, and there won't be any runtime warnings either. Here are the methods I used in the testbed; if you paste directly from the forum, you can be sure the signatures are correct:

#pragma mark -
#pragma mark Text View Delegate Methods
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
NSLog(@"textViewShouldBeginEditing");
return YES;
}
- (void)textViewDidBeginEditing:(UITextView *)textView {
NSLog(@"textViewDidBeginEditing");
}
- (void)textViewDidChange:(UITextView *)textView {
NSLog(@"textViewDidChange");
}
- (void)textViewDidChangeSelection:(UITextView *)textView {
NSLog(@"textViewDidChangeSelection");
}
- (BOOL)textViewShouldEndEditing:(UITextView *)textView {
NSLog(@"textViewShouldEndEditing");
return YES;
}
- (void)textViewDidEndEditing:(UITextView *)textView {
NSLog(@"textViewDidEndEditing");
}

Here's the log for a typical run. This log is from a simulator run. The device run is correct, but the log is harder to read because I have difficulty touching once and only once in the spot I'm aiming for:

[Session started at 2009-08-15 23:25:50 -0700.]
2009-08-15 23:26:00.261 Sam[41788:20b] textViewShouldBeginEditing // 1st msg after click on text view
2009-08-15 23:26:00.296 Sam[41788:20b] textViewShouldBeginEditing
2009-08-15 23:26:00.297 Sam[41788:20b] textViewDidBeginEditing
2009-08-15 23:26:00.298 Sam[41788:20b] textViewDidChangeSelection // last msg after click on text view
2009-08-15 23:26:00.317 Sam[41788:20b] textViewDidChange // 1st back space
2009-08-15 23:26:14.085 Sam[41788:20b] textViewDidChange // 2nd back space
2009-08-15 23:26:14.556 Sam[41788:20b] textViewDidChange // 3rd back space
2009-08-15 23:26:16.967 Sam[41788:20b] textViewDidChangeSelection // 1st click in text view
2009-08-15 23:26:18.591 Sam[41788:20b] textViewDidChangeSelection // 2nd click in text view
2009-08-15 23:26:19.191 Sam[41788:20b] textViewDidChangeSelection // 3rd click in text view
2009-08-15 23:26:23.854 Sam[41788:20b] textViewShouldEndEditing // 1st msg after sending resign
2009-08-15 23:26:23.854 Sam[41788:20b] textViewShouldEndEditing
2009-08-15 23:26:23.856 Sam[41788:20b] textViewShouldEndEditing
2009-08-15 23:26:23.858 Sam[41788:20b] textViewDidEndEditing // last msg after sending resign

The DidChangeSelection message is sent for each click in the view, even if I repeatedly click in the same spot so that the caret doesn't move.

Hope that helps!
- Ray

Aug 16, 2009 9:49 AM in response to RayNewbie

Hi Ray,

Thanks for the reply, and the explanation. It helps.

In my code, I did not have the following two lines- so I added them.

#pragma mark -
#pragma mark Text View Delegate Methods


But the app has the same behavior as before. I am pulling my hair out. I also have the debug NSLog statements, but the log does not indicate that the two methods are called. I made sure that the method signatures are spelled correctly. What can we do next?

Thx, Sam.

Aug 16, 2009 6:08 PM in response to RayNewbie

Hi Ray,

I discovered what causes the problem but don't know how to fix it.

Here's what I found. I wrote a sample app and the behavior was same as in your case. All delegate methods were called appropriately.

So far so good.... - but when , I marked the text for the UITextView as not editable in app's NIB, the *BeginEditing methods were not called even though, in the code where the delegate is set, the text is marked as editable. Am I making sense here?


2009-08-16 17:53:45.503 TV[1595:20b] self = <<MainView: 0x50c820>> <--- Text marked editable in NIB
2009-08-16 17:53:48.262 TV[1595:20b] textViewShouldBeginEditing
2009-08-16 17:53:48.275 TV[1595:20b] textViewShouldBeginEditing
2009-08-16 17:53:48.275 TV[1595:20b] textViewDidBeginEditing
2009-08-16 17:53:54.515 TV[1595:20b] textViewShouldEndEditing
2009-08-16 17:53:54.515 TV[1595:20b] textViewShouldEndEditing
2009-08-16 17:53:54.518 TV[1595:20b] textViewShouldEndEditing
2009-08-16 17:53:54.520 TV[1595:20b] textViewShouldEndEditing
2009-08-16 17:53:54.521 TV[1595:20b] textViewDidEndEditing
2009-08-16 17:53:54.521 TV[1595:20b] textViewDidEndEditing
[Session started at 2009-08-16 17:54:23 -0700.]
2009-08-16 17:54:26.752 TV[1612:20b] self = <<MainView: 0x526f20>> <--- Text not marked editable in NIB
2009-08-16 17:54:32.198 TV[1612:20b] textViewShouldEndEditing
2009-08-16 17:54:32.198 TV[1612:20b] textViewShouldEndEditing
2009-08-16 17:54:32.199 TV[1612:20b] textViewShouldEndEditing
2009-08-16 17:54:32.200 TV[1612:20b] textViewShouldEndEditing
2009-08-16 17:54:32.200 TV[1612:20b] textViewDidEndEditing
2009-08-16 17:54:32.200 TV[1612:20b] textViewDidEndEditing
2009-08-16 17:54:39.581 TV[1612:20b] textViewShouldBeginEditing
2009-08-16 17:54:39.584 TV[1612:20b] textViewShouldBeginEditing
2009-08-16 17:54:39.584 TV[1612:20b] textViewDidBeginEditing
Terminating in response to SpringBoard's termination.

Can you please confirm this behavior in your app too? Ray - we can take this offline at shnaps52@gmail.com if you like.

In my real app, I have the similar thing going - UITextView is not marked as editable, but the code enables it. I did not like the idea that the keyboard pops up if the user touches/clicks on the editable text. I want the editing to begin only when the editButton is touched.

The idea of using the 'editable' property of the text was convenient to me - but the side effects are not welcome! 🙂

Sam.

Aug 16, 2009 11:39 PM in response to Shnaps

Shnaps wrote:
... when , I marked the text for the UITextView as not editable in app's NIB, the *BeginEditing methods were not called

Ookay.. I unchecked Editable in the IB Text View Attributes panel and added a button to toggle the text view's editable property ON or OFF. Here's the controller implementation for reference:

// SamViewController.m
#import "SamViewController.h"
@implementation SamViewController
@synthesize theTextView;
@synthesize buEdit;
- (void)setEditTitle {
if ([theTextView isEditable])
[buEdit setTitle:@"Edit Off" forState:UIControlStateNormal];
else
[buEdit setTitle:@"Edit On" forState:UIControlStateNormal];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setEditTitle];
}
- (IBAction)edit {
if ([theTextView isEditable]) {
[theTextView resignFirstResponder];
theTextView.editable = NO;
}
else
theTextView.editable = YES;
[self setEditTitle];
}
- (IBAction)done {
[theTextView resignFirstResponder];
}
- (void)dealloc {
[buEdit release];
[theTextView release];
[super dealloc];
}
#pragma mark -
#pragma mark Text View Delegate Methods
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
NSLog(@"textViewShouldBeginEditing");
return YES;
}
- (void)textViewDidBeginEditing:(UITextView *)textView {
NSLog(@"textViewDidBeginEditing");
}
- (void)textViewDidChange:(UITextView *)textView {
NSLog(@"textViewDidChange");
}
- (void)textViewDidChangeSelection:(UITextView *)textView {
NSLog(@"textViewDidChangeSelection");
}
- (BOOL)textViewShouldEndEditing:(UITextView *)textView {
NSLog(@"textViewShouldEndEditing");
return YES;
}
- (void)textViewDidEndEditing:(UITextView *)textView {
NSLog(@"textViewDidEndEditing");
}
@end

I got results similar to your post, but on this system, those results are easily explained. I found that turning the editable property on always gave first responder status to the text view. I.e. programmatically changing theTextView.editable from NO to YES immediately brings up the keyboard and activates the caret. In this case there are no ShouldBegin or DidBeginEditing messages, and we shouldn't expect any because editing was started programmatically (i.e. the delegate is only there to customize the response to user actions). Of course after touching the "Edit On" button, a subsequent touch on the text view doesn't cause the delegate to get any BeginEditing messages, because editing has already started.

So over here, there's no indication that unchecking Editable in IB did anything unusual. In any case, if that box isn't checked, there's no way to begin editing without first setting the property programmatically.

Were you able to set the editable property to YES in code without activating the keyboard and caret? If so, I don't think I'll be able to reproduce your result. When you did your tests, is it possible you didn't consider that the keyboard and caret were already active when you expected a touch on the text view to produce BeginEditing messages?

- Ray

p.s.: You can ignore the #pragma lines. A pragma is a directive to the build system which has no effect on the source code. Sometimes a pragma is used to modify the compiler options for a certain block of code, often to turn off a particular warning. In the above example, the pragma lines are just formatting the list of methods that Xcode displays when you expand the Function Menu in the center of the Navigation Bar in an Editor window. - R

Aug 17, 2009 7:21 PM in response to RayNewbie

Hi Ray,

Your explanation makes sense about the two delegate methods not being called when the text is set "editable" programmatically. That satisfies my curiosity. I have marked the text to be "editable" in the IB and am good for the the app.

I was able to set the text to be editable to YES without activating the keyboard. The keyboard would be activated when a button in the app was touched.

I had to do this because the text gets hidden when the keyboards appears. In the delegate method, I slide the text up so the user can see what is being typed, and when the "done" button is touched, the text is slid down to the original position.

-Sam-

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

A question about UITextView delegate methods....

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.