I have UITextField and I have
#property (nonatomic, assign) id <UITextFieldDelegate> delegate;
After pressing a done button on keybord, it should dismiss. Can someone tell how I can do it using this property?
The dismissing of the keyboard does not happen merely by being a delegate of the UITextField. Your delegate must dismiss it.
In the viewDidLoad in your controller you must assign the delegate, or set it up in Interface Builder:
- (void)viewDidLoad {
self.textField.delegate = self;
}
Then in your controller, implement the following delegate method.
#pragma mark - UITextFieldDelegate
// This method gets called when you hit the enter key on the keyboard,
// or in this case 'DONE'. The textfield is asking if it should put
// a carriage return in the field. This is our opportunity to dismiss
// the keyboard.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder]; // This is what hides the keyboard
return NO;
}
Further reading:
Responder Chain - developer.apple.com
UITextFieldDelegate Protocol Reference - developer.apple.com
Link didEndOnExit to a method that has [self resignFirstResponder]
Related
I have a DetailViewController, which implementation file contains this code:
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController <UITextFieldDelegate>
{
__weak IBOutlet UITextField *nameField;
__weak IBOutlet UITextField *numberField;
}
#end
In my storyboard, I have set the ViewController's to DetailViewController and connected the delegate of both of my UITextFields to my DetailViewController. The implementation file of my DetailViewController contains this method to dismiss the keyboard when tapping somewhere other than the text field:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
This method is not called though, I have tested this using a breakpoint. What could be going wrong?
rdelmar is correct, the code you have only gets triggered when the user hits the "return" key on the keyboard, not when they click outside of the keyboard.
To get the behavior you are looking for, I'd add a Tap Gesture Recognizer to the view behind your text field, then put [nameField resignFirstResponder]; and [numberField resignFirstResponder]; in the tap gesture recognizer's code.
I created a sample project
added to the viewcontroller
added a textfield and connected its delegate
write the code in viewcontroller
(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
it worked fine.Tried weak it also worked both as instance variable and property
So check if that you are reallocating it anywhere and also check its memory is same there using breakpoint
Why do you use _weak? Remove it.
In your .m file do (in viewDidLoad):
[nameField setDelegate:self];
Same for the other textfield(s).
I want to make the keyboard disappear when the user clicks the "return" button, I was told to use
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[tf resignFirstResponder];
return YES;
}
But nothing happens when I click the "return" button, the method isn't even being called. I am doing this in
#interface gameOverMenu : UIView
not in the ViewController. I also don't use interface builder. What should I do?
You need to make sure you implement the UITextFieldDelegate and set your UITextField delegate to self. In your .h file:
#interface gameOverMenu : UIView <UITextFieldDelegate>
And somewhere in your .m file (viewDidLoad: maybe):
self.yourTextField.delegate = self;
Now your -(BOOL)textFieldShouldReturn:(UITextField *)textField method should be called.
Make sure that you have set the parent class (whatever it is) as a UITextFieldDelegate
I just can't make the "Done" button to quit the keyboard.
I used this in my controller.h file
- (IBAction)textFieldDoneEditing:(id)sender;
and this for my controller.m file
- (IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponer];
}
and I'm mixed up in wiring the .xib part.
Make the controller a delegate of the UITextField/UITextView in IB or from code like textField.delegate = self;
Editted:
For this you need to declare the controller a delegate of UITextFieldDelegate/UITextViewDelegate as
#interface Controller : <UITextFieldDelegate> { ...
, then override the method:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
for UITextField and
-(BOOL)textViewShouldEndEditing:(UITextView *)textView{
[textView resignFirstResponder];
return YES;
}
for UITextView
In your .xib, right click on your text view, drag to "File's Owner", and click "delegate". Should work now?
Edit: Whoops, sorry I'm an idiot, do what that other guy says. If you don't know how to set the delegate in code though, you can do it my way in IB.
Let me make my first contribution:
If you have multiple text fields, group them in a #property (strong, nonatomic)
*.h
#property (strong, nonatomic) IBOutletCollection(UITextField) NSArray *collectingData;
*.m
-(BOOL)textFieldShouldReturn:(UITextField *)boxes
{
for (UITextField *boxes in collectingData) {
[boxes resignFirstResponder];
}
return YES;
}
How to call a custom function when the user touches outside of the UITextField that has keyboard focus?
My goal is to call a function for textfield validation.
I tried this:
// Dismiss Keyboard
- (void)touchesEnded: (NSSet *)touches withEvent: (UIEvent *)event {
for (UIView* view in self.view.subviews) {
if ([view isKindOfClass:[UITextField class]])
{
[view resignFirstResponder];
[self validationForNoOfPassengers];
}
}
}
validationForNoOfPassengers is my method to check for validation. The problem here is that when I tap on other UI controls it does not call the above method. Above method is called only when touched outside on the screen (but not on UIcontrols). Any guidance?
Set your view controller (or some other object) to be the text field's delegate. Do the validation in -textFieldShouldEndEditing: or -textFieldDidEndEditing:.
EDIT
See my answer here for a better, general purpose solution that you can drop into any project.
ORIGINAL ANSWER
Other answers have suggested doing your validation in the text field delegate's textFieldShouldEndEditing: or textFieldDidEndEditing: methods. As you have discovered, when you touch a control, your text field doesn't send those messages to its delegate.
It doesn't send those messages because it is not ending editing. The text field remains first responder (the keyboard focus) when you touch another non-text control.
I don't know if you have just one or two text fields that have validation, or a lot of text fields that have validations. I don't know if you have just one or two non-text controls or a lot of non-text controls. The best solution for you really depends on what you have.
What you'd really like to do is check, on each new touch, whether there is a first responder, if if so, whether the new touch is outside the first responder. If so, send resignFirstResponder to the current first responder (which will make it send textFieldShouldEndEditing: to its delegate), and only proceed if resignFirstResponder returns YES.
If you only have one text field, you can make your top-level view be a subclass of UIView and override the hitTest:withEvent: method, like this:
MyView.h
#import <UIKit/UIKit.h>
#interface MyView : UIView
#property (weak, nonatomic) IBOutlet UITextField *textField;
#end
MyView.m
#import "MyView.h"
#implementation MyView
#synthesize textField;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
return (hitView != self.textField
&& self.textField.isFirstResponder
&& ![self.textField resignFirstResponder])
? nil : hitView;
}
#end
It turns out that hitTest:withEvent: is actually called several times (three in my testing) per touch. So you don't just want to present an alert in textFieldShouldEndEditing: if the validation fails - you need to keep track of whether the alert is already on screen. Otherwise you will see the alert pop up repeatedly.
The above method will get ugly if you have several text fields. You will have to check each one to see if it is currently first responder and not the touched view. It would be much easier if you could just ask the system for the current first responder.
There is a method that will return the current first responder: you can send firstResponder to [[UIApplication sharedApplication] keyWindow] to get the current first responder (or null if there is no first responder). Unfortunately, the firstResponder message is a public API. If you use it, you might not be allowed into the App Store.
If you decide you want to use it, here's what you put in MyView.m:
MyView.m (revised)
#import "MyView.h"
#protocol MyViewFirstResponderProtocol
// Have to declare the message so the compiler will allow it.
- (UIResponder *)firstResponder;
#end
#implementation MyView
#synthesize textField;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSLog(#"hitTest for event %#", event);
UIView *hitView = [super hitTest:point withEvent:event];
UIResponder *firstResponder = [(id)self.window firstResponder];
return (firstResponder
&& hitView != firstResponder
&& ![firstResponder resignFirstResponder])
? nil : hitView;
}
#end
Set a delegate to your text field and implement the textFieldDidEndEditing:
method (in a class that conforms to the UITextFieldDelegate protocol) and call
your function in it:
void
do_something(void)
{
return;
}
/* ... */
- (void)textFieldDidEndEditing:(UITextField *)textField
{
do_something();
}
Try overriding resignFirstResponder and performing your validation there.
I have a class that needs to ask the user a question and wait for the users response to determine the next action. What would be the best way to do this? Using a delegate? How? I have a UITextField and a UITextField in the class.
Thanks
It all depends upon how you wish for the user to submit the data. The most user friendly way is to do as TahoeWolverine explained and implement - (BOOL)textFieldShouldReturn:(UITextField *)textField from UITextFieldDelegate. In order to use this, the class that implements textFieldShouldReturn: must have <UITextFieldDelegate> protocol in its interface declaration; moreover, the textfield in question must have the UITextFieldDelegate-implementing class set as its delegate. In most cases those would look like this:
#interface SomeViewController : UIViewController <UITextFieldDelegate> {
UITextField *myField;
}
#property (nonatomic, retain) IBOutlet UITextField *myfield
#end
and somewhere in the implementation:
[[self myField] setDelegate:self];
Finally, implementing the UITextFieldDelegate protocol:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == [self myField]) {
[self doSomethingWithText:[[self myField] text]];
}
}
Hope that helps.
Yes, you should use a delegate, and link that to the keyboard's done button (I'm assuming that you're presenting the user a keyboard). Simply link your delegate to the return key of the keyboard, and that should do the trick.