UITextField Target/Action vs Delegate Methods - ios

I used to use XCode the develop my apps and using that; I could create a link up in IB/Storyboard that synthesized this methods:
- (void)addTarget:(id)target action:(SEL)action forControlEvents: (UIControlEvents)controlEvents
for when
However, no I'm doing it all programmatically (in rubymotion, though not necessarily relevant) and looking into the documentation for UITextField I found some delegate methods, which I implemented as follows:
def textFieldShouldReturn(text_field)
text_field.resignFirstResponder
end
def textFieldShouldEndEditing(text_field)
# this is for validations; don't set a first responder here
true
end
def textFieldDidEndEditing(text_field)
text_field == #email_field ? #password_field.becomeFirstResponder : delegate.validate_login_info
end
But using this, I found that I could not tab through the input fields (of which I have two; email and password) as I could before with the addTarget approach.
What is the difference between these two approaches? Does the former implement the latter behind the scenes? I don't understand why one will allow me to tab through and the other won't. Did I just implement the delegate methods differently than the target/action approach does behind the scenes?
Feedback appreciated,
pachun

This has nothing to do with target/action. I am assuming you mean in Interface Builder you would drag from the UITextField to the File's Owner and select delegate from the HUD.
Doing the above would have the effect of assigning the textField's delegate which you would need to do in code like this
#email_field.delegate = self
#password_field.delegate = self
the above is assuming that the class that creates the UITextField's will act as their delegate.

I don't know if there's any difference between delegation and target/action in this case,but with delegation this way works:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.firstTextField)
{
[self.secondTextField becomeFirstResponder];
}
else if (textField == self.secondTextField)
{
[textField resignFirstResponder];
// proceed with login
}
return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
// Validation
return YES;
}
Regards

Related

textFieldShouldBeginEditing: Only Recognizes 1 textField

I have two text fields in my interface. txtUser allows the user to enter their username and txtPass allows the user to enter their password. I have programmatically assigned tags in the viewDidLoad method. I use these tags in order to identify the different text fields. The issue is that the textFieldShouldBeginEditing method only recognizes txtPass, while ignoring the txtUser. Both of these variables are linked to their respective text fields, so that's not what's causing the issue. Below is my code:
- (void)viewDidLoad{
[super viewDidLoad];
self.txtUser.tag=10;
self.txtPass.tag=20;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if (textField.tag == 10){
self.btnNext.enabled = YES;
self.btnPrevious.enabled = NO;
}else if(textField.tag == 20){
self.btnNext.enabled = NO;
self.btnPrevious.enabled = YES;
}
return YES;
}
Are you setting the delegate for the text fields anywhere?
self.txtUser.delegate=self;
self.txtPass.delegate=self;
Also make sure you implement UITextFieldDelegate on your view controller.
#interface YourViewController: UIViewController<UITextFieldDelegate>
My semi-confident guess is that you've setup the delegate, but not the outlets, so the code that you think is assigning the tags is not working (assigning .tag = 10 to nil).
The incoming tag is then zero (the default) for both fields, so the else branch in the delegate code is always running.
Fix by setting the outlets (or by setting the tags in IB).

How to stop the UIKeyboard return key from working

I have a UITextField thats currently in a UITableViewCell, when you select the UITextField the UIkeyboard automatically comes up.
I would like to know how I can just ignore the return key when its pressed.. there is a feature I have no implemented yet to skip UITextFields its causing me some errors and before I preview my app I would like to disable it to avoid any confusion.
Sure, you'll need to use UITextFieldDelegate, specifically, textFieldShouldReturn:. All you have to do is specify that your class will conform to this protocol in your interface, and specify that this class as the delegate on the textfield's delegate property and you're good to go. That is, after returning no from textFieldShouldReturn:. Or of course, this can be done conditionally.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (someCondition == YES) {
return NO;
}
return YES;
}

which event to use for readonly textfield when text is changed

I have a readonly text field. I want that when the value is changed to this field , to set another text field also.
Which event should I use. tried with editingChanged , but it's not getting called.
pls help.
If the text field is readonly, then you must set the text programmatically, right? In that case, when you set the text, set the text of the other text field at the same time.
If I misunderstood your question, and the user edits the textfield, you can listen for changes this way:
[textField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventValueChanged];
And handle the callback the following way:
- (void)textFieldDidChange:(UITextField *)textField
{
// Handle change
}
From Apple documentation
textFieldShouldBeginEditing: Asks the delegate if editing should begin
in the specified text field.
(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
Parameters textField - The text field for which editing is about to
begin.
Return Value YES if an editing session should be initiated; otherwise,
NO to disallow editing.
Discussion When the user performs an action that would normally
initiate an editing session, the text field calls this method first to
see if editing should actually proceed. In most circumstances, you
would simply return YES from this method to allow editing to proceed.
Implementation of this method by the delegate is optional. If it is
not present, editing proceeds as if this method had returned YES.
So use something like:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
BOOL editable;
if (textField == myReadOnlyTextField) {
editable = NO;
} else if (textField == myEditableTextField) {
editable = YES;
} else {
// editable = YES/NO/Other Logic
}
return editable;
}
Also in order for the delegate methods to get called your interface should conform to the UITextfieldProtocol: add this to your .h file <UITextFieldDelegate> so it looks like this:
#interface ViewController : UIViewController <UITextFieldDelegate>
Implement this delegate method if you are implementing in ios.
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange{}
If you are implementing in macos then use below delegate method:-
-(void)controlTextDidChange

How to disable keyboard appearing when hitting on a text field , iOS?

I have a text field , and i need when the user presses it to show a custom picker.
The picker is shown fine , but the problem is that the keyboard appears on the bottom and i dont want that.
This is an iPad project which i am trying to convert from my iphone one. On the iPhone , this works well and the keyboard is always hidden.
What could i be missing/forgetting to do here ?
EDIT
For future reference what actually happened here , was that in fact both times (iphone & ipad) the keyboard was not hidden. I just thought that it was hidden in the iphone because my picker , which was popping from the bottom was hiding the keyboard as it was on top of it. But on ipad this wasnt the case.
Anyway i fixed it , using the delegate method suggested below.
Caution , i accepted this answer cause it was the one answering specifically what i wanted. The rest of the answers are correct and my considered better for other implementations.
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
// Here You can do additional code or task instead of writing with keyboard
return NO;
}
this delegate method will get called first when you hit to textfield and if you write NO as a boolean value means you dont want to begin editing so it will not present Keyboard.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textfield == yourtextField)
{
[textfield resignFirstResponder];
// Show you custom picker here....
return NO;
}
}
and you need to implement the uitextfielddelegate in the controller.
and give assign the delegate to yourtextField.
Use textfield delegate.
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return NO;
}
It looks like all of these answers take one approach, to simply deny the keyboard before it comes up. This prevents first responder status, which has many advantages.
One simple approach that allows you to maintain first responder status is to create an empty view and assign that to the inputView property on your input field. If you are using iOS 9 (or later?) you will also have to get rid of the inputAssistantItem objects as well.
UITextField *field = [[UITextField alloc] init];
field.inputView = self.emptyKeyboard.view;
UITextInputAssistantItem *aItem = [field inputAssistantItem];
aItem.leadingBarButtonGroups = #[];
aItem.trailingBarButtonGroups = #[];
Then if you want to control the field from an alternate view controller, you can do so by adding targets:
[field addTarget:self.numberPad action:#selector(editingBegan:) forControlEvents:UIControlEventEditingDidBegin];
[field addTarget:self.numberPad action:#selector(editingEnded:) forControlEvents:UIControlEventEditingDidEnd];
[field addTarget:self.numberPad action:#selector(fieldChanged:) forControlEvents:UIControlEventEditingChanged];
It is also possible to do this a lot more cleanly by subclassing UITextField.
Use the textField Delegate,
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
textField=nil;
return NO;
}
swift 3.0 version
First set the delegate for the text field
self.textfield.delegate = self
Then in an extension
extension ViewController: UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
// Here you can do for Specific text Field by
if (textField==(the text field you don't want to show keyboard)) {
NSLog(#"don't show keyboard");
return NO;
}
else {
return YES;
}
}
Swift 3/4
Add:- UITextFieldDelegate in your class.
Add:- self.textField.delegate = self In ViewDidLoad
last one just add this func -
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}

How do I dismiss the iOS keyboard?

I have a UITextfield that i'd like to dismiss the keyboard for. I can't seem to make the keyboard go away no matter what code i use.
If you have multiple text fields and don't know which one is first responder (or you simply don't have access to the text fields from wherever you are writing this code) you can call endEditing: on the parent view containing the text fields.
In a view controller's method, it would look like this:
[self.view endEditing:YES];
The parameter forces the text field to resign first responder status. If you were using a delegate to perform validation and wanted to stop everything until the text field's contents were valid, you could also code it like this:
BOOL didEndEditing = [self.view endEditing:NO];
if (didEndEditing) {
// on to the next thing...
} else {
// text field must have said to first responder status: "never wanna give you up, never wanna let you down"
}
The endEditing: method is much better than telling individual text fields to resignFirstResponder, but for some reason I never even found out about it until recently.
[myTextField resignFirstResponder]
Here, second paragraph in the Showing and Hiding the Keyboard section.
I've discovered a case where endEditing and resignFirstResponder fail. This has worked for me in those cases.
ObjC
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder) to:nil from:nil forEvent:nil];
[self setEditing:NO];
Swift
UIApplication.shared.sendAction(#selector(resignFirstResponder), to: nil, from: nil, for: nil)
There are cases where no text field is the first responder but the keyboard is on screen.
In these cases, the above methods fail to dismiss the keyboard.
One example of how to get there:
push the ABPersonViewController on screen programmatically; open any contact;
touch the "note" field (which becomes first responder and fires up the keyboard);
swipe left on any other field to make the "delete" button appear;
by this point you have no first responder among the text fields (just check programmatically) but the keyboard is still there. Calling [view endEditing:YES] does nothing.
In this case you also need to ask the view controller to exit the editing mode:
[viewController setEditing:NO animated:YES];
I suggest you add and action on your header file:
-(IBAction)removeKeyboard;
And in the implementation, write something like this:
-(IBAction)removeKeyboard
{
[self.textfield resignFirstResponder];
}
In the NIB file, connect from the UITextFiled to the File's Owner on the option DidEndOnExit. That way, when you press return, the keyboard will disappear.
Hope it helps!
In your view controller YourViewController.h file, make sure you implement UITextFieldDelegate protocol :
#interface YourViewController : <UITextFieldDelegate>
#end
Then, in YourViewController.m file, implement the following instance method:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.yourTextField1 resignFirstResponder];
[self.yourTextField2 resignFirstResponder];
...
[self.yourTextFieldn resignFirstResponder];
}
To resign any text field in the app
UIApplication.shared.keyWindow?.endEditing(true)
This approach is clean and guarantied to work because the keyWindow is, by definition, the root view of all possible views displaying a keyboard (source):
The key window receives keyboard and other non-touch related events. Only one window at a time may be the key window.
This will resign one particular text field
// Swift
TextField.resignFirstResponder()
// Objective C
[TextField resignFirstResponder];
To resign any text field use below code
// Swift
self.view!.endEditing(true)
// Objective C
[self.view endEditing:YES];
as a last resort 💩
let dummyTextView = UITextView(frame: .zero)
view.addSubview(dummyTextView)
dummyTextView.becomeFirstResponder()
dummyTextView.resignFirstResponder()
dummyTextView.removeFromSuperview()
If you don't know which textField is the first responder you can find it. I use this function:
UIView *resignFirstResponder(UIView *theView)
{
if([theView isFirstResponder])
{
[theView resignFirstResponder];
return theView;
}
for(UIView *subview in theView.subviews)
{
UIView *result = resignFirstResponder(subview);
if(result) return result;
}
return nil;
}
Then in your code call:
UIView *resigned = resignFirstResponder([UIScreen mainScreen]);
You just replace yourTextFieldName with, you guessed it! your textfield. This will close the keyboard.
[yourTextFieldName resignFirstResponder];
-(void)methodName
{
[textFieldName resignFirstResponder];
}
call this method (methodName) with didEndOnExit
For Swift 3
You can hide the keyboard like this:
textField.resignFirstResponder()
If you want to hide the keyboard when the user press the "intro" button, you have to implement the following UITextFieldDelegate method:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
// your code
[textField reloadInputViews];
}
3 Simple & Swift steps
Add UITextFieldDelegate to your class as below:
class RegisterVC: UIViewController, UITextFieldDelegate {
//class implementation
}
in class implementation, add the delegate function textFieldShouldEndEditing::
internal func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return true
}
and as a last step, set your UITextField(s) delegate(s) to self, in somewhere appropriate. For example, inside the viewDidLoad function:
override func viewDidLoad(){
super.viewDidLoad()
myTextField1.delegate = self
myTextField2.delegate = self
..
..
}
Now, whenever user hits the return key, keyboard will dismiss.
I prepared an example snippet too, you can check it from here.
Set up the "Did End On Exit" event in Xcode (right click on your text field).
Realize this method:
-(IBAction) closeKeyboard:(id) sender {
[_txtField resignFirstResponder];
}

Resources