UIText view delegate issue - iphone

I want to resign keyboard from UItextview. How to implement UItextView delegate method programmatically.

If u want that ur keyboard is resigned when click on return then u have to write, implement this method....
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Just make it copy and paste....:)

Make sure you declare support for the UITextViewDelegate protocol.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}

You should use the UITextViewDelegate. You have to declare the use of the protocol in your class header like:
#interface YourClass:NSObject<UITextViewDelegate>
Then in your .m, you should set your class as delegate in some point with something like:
textView.delegate = self;
Then, in your .m again, you have to implement the delegate methods, in particular:
textViewDidChange:
You can read the protocol reference at http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextViewDelegate_Protocol/Reference/UITextViewDelegate.html for more information.

There is no specific delegate method for UITextview to know when user hits "RETURN"
So you can do like this
//In .h File
#interface BlahBlah : UIViewController <UITextViewDelegate>
#property(nonatomic, retain) IBOutlet UITextView *myTextView;
#end
//In .m File
#implementation BlahBlah
#synthesis myTextView;
//In some method, can be viewDidLoad OR viewDidAppear . your convenience ;)
{
self.myTextView.delegate = self;
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}

Related

textViewDidEndEditing is not called

I'm new to iOS development.
I have written header file following like this
#interface TextView : UITextView <UITextViewDelegate, UIPopoverControllerDelegate>
in TextView.h.
The implementation file code is following :
- (BOOL)textViewShouldBeginEditing:(TextView *)textView
{
ZWLog(#"called should begin edit");
return YES;
}
- (void)textViewDidBeginEditing:(TextView *)textView
{
ZWLog(#"called did begin edit");
}
- (BOOL)textViewShouldEndEditing:(TextView *)textView
{
ZWLog(#"called should end editing");
return YES;
}
- (void)textViewDidEndEditing:(TextView *)textView
{
ZWLog(#"view did end edit");
return YES;
}
- (BOOL)textView:(TextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
//my own code
return YES;
}
- (void)textViewDidChange:(TextView *)textView
{
//my own code
}
When i start typing a character in UITextView, I got response from
textViewShouldBeginEditing.
textViewDidBeginEditing.
shouldChangeTextInRange.
textViewDidChange.
But I didn't get any response from textViewDidEndEditing or textViewShouldEndEditing. Do you have any idea why these are not getting called?
Thanks for your answers.
textViewDidEndEditing is called when textfield resigns its first responder, when the keyboard disappears.
make sure you've linked your delegate properly from .xib
and use the below methods as it is and take a look it will get called
-(BOOL)textViewShouldEndEditing:(UITextView *)textView
{
ZWLog(#"textViewShouldEndEditing");
return TRUE;
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
ZWLog(#"shouldChangeTextInRange");
// Any new character added is passed in as the "text" parameter
if ([text isEqualToString:#"\n"])
{
[textView resignFirstResponder];
return FALSE;
}
// For any other character return TRUE so that the text gets added to the view
return TRUE;
}
MAke Sure that your delegate is attched in your XIB file with your
TextView if it is in XIB file.

Textfield event is never called in delegate

In my interface I have:
#interface MainViewController : UIViewController <SKProductsRequestDelegate, SKPaymentTransactionObserver, UITextFieldDelegate> {
UITextField *Stock;
// ....
}
This is the implementation I have:
- (BOOL)Stock:(UITextField *)textField shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([[textField text] isEqualToString:#"\n"]) {
[textField resignFirstResponder];
return NO;
}
return YES;
}
In the viewDidLoad I have Stock.delegate = self;
I am expecting this method is called after any character is typed in the text field. But this routine is never called. What is the problem?
Thanks
If this is a UITextField, you've just implemented a random method. The actual delegate method is
-textField:shouldChangeCharactersInRange:replacementString:
Try providing that one.
Did you wire the TextField (Stock in your case) Delegate to FileOwner ?
If not then try this in viewDidLoad method of the Controller
Stock.delegate = self;
Or you can just wire it in IB.
Declare MainViewController conforming UITextFieldDelegate:
#interface MainViewController : UIViewController < UITextFieldDelegate >
To be called this method of UITextFieldDelegate should be declared as:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
In code or in IB MainViewController should be set to be delegate.
Correct and it will be fired as supposed.

resignFirstResponder UITextView

I am using a UITEXTVIEW. I am trying to send a resignFirstResponder when the done button is pressed. I am not sure how to trigger the method containing the resignFirstResponder line.
I have set the UITextView's delegate to the File's Owner in Interface Builder. This is my viewcontroller's header and implementation file:
#import <Foundation/Foundation.h>
#import "Question.h"
#interface CommentQuestionViewController : UIViewController {
Question *question;
IBOutlet UILabel *questionTitle;
IBOutlet UITextView *inputAnswer; //this is the textview
}
#property (nonatomic, retain) UILabel *questionTitle;
#property (nonatomic, retain) Question *question;
#property (nonatomic, retain) UITextView *inputAnswer;
- (void) addButton:(id)sender isLast:(BOOL)last;
- (void) setQuestionId:(NSString*)quId withTitle:(NSString*)quTitle number:(NSString*)quNum section:(NSString*)sId questionType:(NSString*)qt;
#end
#import "CommentQuestionViewController.h"
#implementation CommentQuestionViewController
#synthesize questionTitle, question, inputAnswer;
- (void) addButton:(id)delegate isLast:(BOOL)last{
UIBarButtonItem *anotherButton;
anotherButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStylePlain target:delegate action:#selector(finishQuestionnaire:)];
self.navigationItem.rightBarButtonItem = anotherButton;
[anotherButton release];
}
-(void)viewDidLoad{
//self.questionTitle.text = question.qTitle;
[[self questionTitle] setText:[question qTitle]];
[super viewDidLoad];
NSString *str = [NSString stringWithFormat:#"Question %#", [question qNumber]];
//self.title = str;
[self setTitle:str];
[str release];
}
-(void) setQuestionId:(NSString*)quId withTitle:(NSString*)quTitle number:(NSString*)quNum section:(NSString*)sId questionType:(NSString*)qt{
question = [[Question alloc]init];
[question setQId:quId];
[question setQTitle:quTitle];
[question setQNumber:quNum];
[question setSectionId:sId];
[question setQType:qt];
}
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void) textViewDidEndEditing:(UITextView*)textView{
[textView resignFirstResponder];
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[inputAnswer release];
[questionTitle release];
[question release];
[super dealloc];
}
You can try this:
–(BOOL)textView:(UITextView*)textView shouldChangeCharactersInRange:(NSRange)range replacementText:(NSString*)text {
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
else
return YES;
}
Of course, you won't be able to type actual carriage returns if you do this.
After looking at your source code, the link that I had posted is pointless. I thought you were talking about the done key on the keyboard. But now I see that you were talking about an instance UIButton on the navigation bar, right?
Your addButton:isLast: method is looking great so far, but I'd change it a bit so it adheres to the Apple HIG:
- (void)addButton:(id)delegate isLast:(BOOL)last
{
UIBarButtonItem *anotherButton;
anotherButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:delegate
action:#selector(finishQuestionnaire:)];
self.navigationItem.rightBarButtonItem = anotherButton;
[anotherButton release];
}
It's pretty much the same, except this one creates a button with the appropriate style.
Anyway, I don't see how the button is being added since addButton:isLast: is not being called in viewDidLoad:. Add the following line in your viewDidLoad:.
[self addButton:self isLast:NO];
last is redundant in your addButton:isLast: since it's not even being use so I just pass whatever (NO).
You're almost done, but if you press that button, your application would crash since finishQuestionnaire: is not implemented on self (CommentQuestionViewController). And since you want to dismiss the keyboard when the user presses your done button, that's where we will also resign your text view as first responder. Just add the following method:
- (void)finishQuestionnaire:(id)sender
{
[inputAnswer resignFirstResponder];
}
It's BOOL that's it..
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
If that doesn't work please check the following things..
Whether your textView is connected to the textView property defined in your class.. (You can see this in your xib, with an arrow icon).
2.Check whether the textView delegate is written in your .h file.
#interface YourViewController : UIViewController <UITextViewDelegate>
3.Check whether the textView's delegate is assigned.
//set this in the viewDidLoad method
self.textView.delegate = self;
Check for new line character by this method.
-(NSRange)rangeOfCharacterFromSet:(NSCharacterSet *)aSet
Then check the length of the text, if it is one character length, then new line character is entered, not pasted.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
BOOL hasNewLineCharacterTyped = (text.length == 1) && [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location != NSNotFound;
if (hasNewLineCharacterTyped) {
[textView resignFirstResponder];
return NO;
}
return YES;
}

How to make UITextView "Done" button resignFirstResponder?

I am trying to make my editable UITextView resign the keyboard (resignFirstResponder) when the user taps "Done." Using a UITextField, I have been able to do this with the following code:
- (IBAction)doneEditing:(id)sender {
[sender resignFirstResponder];
}
... and then to attach it to the relevant UITextField in Interface Builder to the action "Did End on Exit."
However, with a UITextView, I can't seem to access the "Did End on Exit" action. Any suggestions on how to make this happen?
The accepted answer didn't work for me. Instead, the following delegate method should be invoked like this:
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]){
[textView resignFirstResponder];
return NO;
}else{
return YES;
}
}
Paste that into the class that you assign to be the UITextView delegate and it'll work.
new Answer
On your View, you'd have a UIBarButton ("Done") that is connected to the IBAction below:
- (IBAction)doneEditing:(id)sender {
[textView resignFirstResponder];
}
Where textView is your textView outlet defined in your .h file and connected in Storyboard or .xib file. Like this:
#property (retain, nonatomic) IBOutlet UITextView *textView;
old Answer
Check the following:
Is UITextViewDelegate specified
in .h
Implement delegate method
for uitextview:
textViewShouldEndEditing, return YES
make sure your .m (controller) is the
delegate for uitextview in IB
resignFirstResponder should now
work.
You can implement UITextViewDelegate and wait for "\n", in Swift 4 :
myTextView.delegate = self
// ...
extension MyViewController : UITextViewDelegate {
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
}
To have the done button dismiss the keyboard and resignFirstResponder you have to implement a delegate method.
In your .h implement the UITextFieldDelegate
#interface YourViewController : UIViewController <UITextFieldDelegate>
Then implement the textFieldShouldReturn in your .m
-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Don't forget to link the delegate of UITextField to the file's Owner (very important)

Insert date/time in UITextView when user hits return

Im trying to Insert the current date/time whenever the users hits the return key or starts typing on a UITextView in Xcode but not quite sure where to start.
I know this method is for when clicking into the TextView but doesn't seem to work:
- (void)textViewDidBeginEditing:(UITextView *)textView {
self.txtDetail.text = [self.txtDetail.text stringByAppendingString:#"Hello!"];
}
Thanks
Update:
DetailViewController.h
#interface DetailViewController : UIViewController <UIPopoverControllerDelegate, UISplitViewControllerDelegate> {
UITextView *txtDetail;
}
#property (nonatomic, retain) IBOutlet UITextView *txtDetail;
- (void)textViewDidBeginEditing:(UITextView *)textView;
DetailViewController.m
#synthesize txtDetail;
- (void)textViewDidBeginEditing:(UITextView *)textView {
NSLog(#"Hello");
self.txtDetail.text = [self.txtDetail.text stringByAppendingString:#"Hello!"];
}
Update02:
Ive added this to my .m files:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
BOOL shouldChangeText = YES;
if ([text isEqualToString:#"\n"]) {
// Find the next entry field
txtDetail.text = [txtDetail.text stringByAppendingString:#"\nhey\n"]; }
textView.editable = YES;
shouldChangeText = NO;
[textView becomeFirstResponder];
return shouldChangeText;
}
I get the desired effect (Hey is added in whenever i press return on the keyboard) but i now can't type anything... any ideas?
You have to declare you controller as implementing the UITextViewDelegate Protocol and then connect it as the text view's delegate. Otherwise it never receives the delegate messages at all.
Then you have to implement:
– textView:shouldChangeTextInRange:replacementText:
... to return YES/TRUE otherwise no text gets added.
Update02:
You need to implement all the UITextViewDelegate protocol methods that have a return. If you don't, the text view assumes a NO by default.
See: Text and Web Programming Guide: Managing TextFields and TextViews
You also need to understand the Delegate Pattern.
Replace your method with the below method
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
BOOL shouldChangeText = YES;
if ([text isEqualToString:#"\n"] && textView == detailText)
{
// Find the next entry field
txtDetail.text = [txtDetail.text stringByAppendingString:#"\nhey\n"];
textView.editable = YES;
shouldChangeText = NO;
[textView becomeFirstResponder];
}
return shouldChangeText;
}
The mechanics of delegate calls is a very important part of iOS programming. There is a doc on it in the Apple libraries, and it is also discussed in many good books. The Apress book "Beginning iPhone Programming" is very good and covers delegate methods.