Action of the "Go" button of the ios keyboard - ios

How do I bind an action to the Go button of the keyboard in iOS ?

Objective-C
Assuming you're using a UITextField, you could use the <UITextFieldDelegate> method textFieldShouldReturn.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder]; // Dismiss the keyboard.
// Execute any additional code
return YES;
}
Don't forget to assign the class you put this code in as the text field's delegate.
self.someTextField.delegate = self;
Or if you'd prefer to use UIControlEvents, you can do the following
[someTextField addTarget:self action:#selector(textFieldDidReturn:) forControlEvents:UIControlEventEditingDidEndOnExit];
- (void)textFieldDidReturn:(UITextField *)textField
{
// Execute additional code
}
See #Wojtek Rutkowski's answer to see how to do this in Interface Builder.
Swift
UITextFieldDelegate
class SomeViewController: UIViewController, UITextFieldDelegate {
let someTextField = UITextField()
override func viewDidLoad() {
super.viewDidLoad()
someTextField.delegate = self
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder() // Dismiss the keyboard
// Execute additional code
return true
}
}
UIControlEvents
class SomeViewController: UIViewController {
let someTextField = UITextField()
override func viewDidLoad() {
super.viewDidLoad()
// Action argument can be Selector("textFieldDidReturn:") or "textFieldDidReturn:"
someTextField.addTarget(self, action: "textFieldDidReturn:", forControlEvents: .EditingDidEndOnExit)
}
func textFieldDidReturn(textField: UITextField!) {
textField.resignFirstResponder()
// Execute additional code
}
}

You can connect UITextFiled event Did End On Exit in Connections Inspector. It is triggered after tapping Go / Return / whatever you choose as Return Key in Attributes Inspector.

Related

UITextField: resign keyboard after clearButton is pressed

I have a UITextfield in a storyboard.
ClearButton is set to 'is always visible'
searchTextField.addTarget(self, action: #selector(searchTextFieldDidChange(textField:)), for: .editingChanged)
When the text field changes, this method is called
#objc func searchTextFieldDidChange(textField: UITextField){
if textField.text == "" {
textField.resignFirstResponder()
}
fireSearch()
}
When I clear the text field using backspace, textField.resignFirstResponder() is called, the keyboard vanishes as I want it.
When I clear the text field using the clear button, textField.resignFirstResponder() is called, the keyboard vanishes and appears again immediately.
What can I do that the keyboard keeps being closed when I tap the clear button?
Give this a try...
// conform to UITextFieldDelegate
class ViewController: UIViewController, UITextFieldDelegate {
// assuming this is created in Storyboard
#IBOutlet var searchTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
searchTextField.addTarget(self, action: #selector(searchTextFieldDidChange(textField:)), for: .editingChanged)
// set the delegate
searchTextField.delegate = self
}
#objc func searchTextFieldDidChange(textField: UITextField){
if textField.text == "" {
textField.resignFirstResponder()
}
fireSearch()
}
func textFieldShouldClear(_ textField: UITextField) -> Bool {
// clear the text
// Note: this does NOT fire searchTextFieldDidChange()
textField.text = ""
// resign
textField.resignFirstResponder()
// if you want to fire the search after text has been cleared
//fireSearch()
// return false to stop the default action of the clear button
return false
}
func fireSearch() {
print(#function)
}
}

Keyboard not getting dismissed when MDTimePicker is shown

I got problem while showing timer picker. There are two text fields: 1. first one opens a number pad. 2. second opens time picker from material controls.
Once I start editing first TF & if I tap on second TF the number pad is not getting dismissed even if I tap on Done button.
the done button is created using ToolBar & the method contains "view.endEditing" code. It works fine normally but not in above condition.
override func viewDidLoad() {
super.viewDidLoad()
rateInPointsTextField.delegate = self
}
extension MyAvailabilityVC : UITextFieldDelegate{
let toolbar = UIToolbar()
toolbar.sizeToFit()
//done button for toolbaar
let done = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed))
toolbar.setItems([done], animated: false)
self.rateInPointsTextField.inputAccessoryView = toolbar
#objc func donePressed(){
self.view.endEditing(true)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.fromTimeTextField{
let timePicker = MDTimePickerDialog()
timePicker.delegate = self
timePicker.tag = 100
timePicker.clockMode = .mode12H
timePicker.show()
self.view.endEditing(true)
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.rateInPointsTextField.resignFirstResponder()
return true
}
}
Confirm UITextFieldDelegate in your view controller & set TF delegate to self
class YourViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var your_tf: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
your_tf.delegate = self;
}
....
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
Now when you will press done/return button of keyboard then keyboard will dismiss. If you want to dismiss from your created button then make call from done #Action fun to textFieldShouldReturn(your_tf) like this.
...
#objc func donePressed(){
textFieldShouldReturn(your_tf)
}

How to hide the keypad after use

Hei, is there an easy way to add - that after the input into a text field and pressing a button the keypad is disappearing from the screen?
I found here this answer: in button action routine write [yourTextField resignFirstResponder]. it will hide your keyboard.
But I dont get it where to place that code [yourTextField resignFirstResponder]
Thanks for help!
If you simply want to dismiss the keyboard when the user presses the return key, simply add this to viewDidLoad in order to receive delegate callbacks from your textfield:
- (void)viewDidLoad
{
[super viewDidLoad];
self.myTextfield.delegate = self;
}
And then implement this method that hides the keyboard when the user presses the return key:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;
}
And in Swift:
override func viewDidLoad() {
super.viewDidLoad()
myTextfield.delegate = self
}
func textFieldShouldReturn(textField: UITextField!) -> Bool {
textField.resignFirstResponder()
return false
}
If you're not pressing the return key, but your own UIButton, you'll have to do something like this:
#IBAction func findBudget(sender: AnyObject) {
myTextfield.resignFirstResponder()
// .. rest of your code.
}

Using "Next" as a Return Key

I use the "Next" value for the "Return Key" to get the Next button in place of the Done button, but (obviously) pressing it doesn't automatically move to the next UITextField in my view.
What's the right way to do this? I have seen many answers, but anyone have a swift solution?
Make sure your text fields have their delegate set and implement the textFieldShouldReturn method. This is the method that is called when the user taps the return key (no matter what it looks like).
The method might look something like this:
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == self.field1 {
self.field2.becomeFirstResponder()
}
return true
}
The actual logic in here might vary. There are numerous approaches, and I'd definitely advise against a massive if/else chain if you have lots of text fields, but the gist here is to determine what view is currently active in order to determine what view should become active. Once you've determined which view should become active, call that view's becomeFirstResponder method.
For some code cleanliness, you might consider a UITextField extension that looks something like this:
private var kAssociationKeyNextField: UInt8 = 0
extension UITextField {
var nextField: UITextField? {
get {
return objc_getAssociatedObject(self, &kAssociationKeyNextField) as? UITextField
}
set(newField) {
objc_setAssociatedObject(self, &kAssociationKeyNextField, newField, .OBJC_ASSOCIATION_RETAIN)
}
}
}
And then change our textFieldShouldReturn method to look like this:
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.nextField?.becomeFirstResponder()
return true
}
Once you've done this, it should simply be a matter of setting each text field's new nextField property in viewDidLoad:
self.field1.nextField = self.field2
self.field2.nextField = self.field3
self.field3.nextField = self.field4
self.field4.nextField = self.field1
Although if we really wanted, we could prefix the property with #IBOutlet, and that would allow us to hook up our "nextField" property right in interface builder.
Change the extension to look like this:
private var kAssociationKeyNextField: UInt8 = 0
extension UITextField {
#IBOutlet var nextField: UITextField? {
get {
return objc_getAssociatedObject(self, &kAssociationKeyNextField) as? UITextField
}
set(newField) {
objc_setAssociatedObject(self, &kAssociationKeyNextField, newField, .OBJC_ASSOCIATION_RETAIN)
}
}
}
And now hook up the nextField property in interface builder:
(Set up your delegate while you're here too.)
And of course, if the nextField property returns nil, the keyboard just hides.
Here is an example in Swift:
I created a screen with 6 UITextFields. I assigned them the tags 1 through 6 in Interface Builder. I also changed the Return key to Next in IB. Then I implemented the following:
import UIKit
// Make your ViewController a UITextFieldDelegate
class ViewController: UIViewController, UITextFieldDelegate {
// Use a dictionary to define text field order 1 goes to 2, 2 goes to 3, etc.
let nextField = [1:2, 2:3, 3:4, 4:5, 5:6, 6:1]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Make ourselves the delegate of the text fields so that textFieldShouldReturn
// will be called when the user hits the Next/Return key
for i in 1...6 {
if let textField = self.view.viewWithTag(i) as? UITextField {
textField.delegate = self
}
}
}
// This is called when the user hits the Next/Return key
func textFieldShouldReturn(textField: UITextField) -> Bool {
// Consult our dictionary to find the next field
if let nextTag = nextField[textField.tag] {
if let nextResponder = textField.superview?.viewWithTag(nextTag) {
// Have the next field become the first responder
nextResponder.becomeFirstResponder()
}
}
// Return false here to avoid Next/Return key doing anything
return false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
There is nothing wrong with the other answers, this is just a different approach with the benefit of being more focused on OOP - imho (although this is a bit more work up front, it can be reused). In the storyboard, I start off adding tags with a distinct range (e.g 800-810) that define the specific order of the fields I want to move between. This has the benefit of working across all subviews in the main view so that one can navigate between UITextField's and UITextView's (and any other control) as needed.
Generally - I typically try to have view controllers message between views and custom event handler objects. So I use a message (aka, NSNotification) passed back to the view controller from a custom delegate class.
(TextField Delegate Handler)
Note: In AppDelegate.swift: let defaultCenter = NSNotificationCenter.defaultCenter()
//Globally scoped
struct MNGTextFieldEvents {
static let NextButtonTappedForTextField = "MNGTextFieldHandler.NextButtonTappedForTextField"
}
class MNGTextFieldHandler: NSObject, UITextFieldDelegate {
var fields:[UITextField]? = []
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
textField.backgroundColor = UIColor.yellowColor()
}
func textFieldDidEndEditing(textField: UITextField) {
textField.backgroundColor = UIColor.whiteColor()
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
return true
}
func textFieldShouldClear(textField: UITextField) -> Bool {
return false
}
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
return true
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
//passes the message and the textField (with tag) calling the method
defaultCenter.postNotification(NSNotification(name: MNGTextFieldEvents.NextButtonTappedForTextField, object: textField))
return false
}
}
This allows my view controller to remain focused on it's main job of handling the messaging between objects, model and view.
(View Controller receives a message from the delegate and passes instructions using the advanceToNextField function)
Note: In my storyboard my custom handler classes are defined using an NSObject and that object is linked into the storyboard as a delegate for the controls that I need monitored. Which causes the custom handler class to be initialized automatically.
class MyViewController: UIViewController {
#IBOutlet weak var tagsField: UITextField! { didSet {
(tagsField.delegate as? MNGTextFieldHandler)!.fields?.append(tagsField)
}
}
#IBOutlet weak var titleField: UITextField!{ didSet {
(titleField.delegate as? MNGTextFieldHandler)!.fields?.append(titleField)
}
}
#IBOutlet weak var textView: UITextView! { didSet {
(textView.delegate as? MNGTextViewHandler)!.fields?.append(textView)
}
}
private struct Constants {
static let SelectorAdvanceToNextField = Selector("advanceToNextField:")
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
registerEventObservers()
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
deRegisterEventObservers()
}
func advanceToNextField(notification:NSNotification) {
let currentTag = (notification.object as! UIView).tag
for aView in self.view.subviews {
if aView.tag == currentTag + 1 {
aView.becomeFirstResponder()
}
}
}
func registerEventObservers () {
defaultCenter.addObserver(self, selector: Constants.SelectorAdvanceToNextField, name: MNGTextFieldEvents.NextButtonTappedForTextField, object: nil)
}
func deRegisterEventObservers() {
defaultCenter.removeObserver(self, name: MNGTextFieldEvents.NextButtonTappedForTextField, object: nil)
}
....
}
Just another way to achieve the result that I found helpful. My app had 11 text fields followed by a text view. I needed to be able to cycle through all fields using the next key and then resign the keyboard following the textview (i.e. other notes).
In the storyboard, I set the tag on all of the fields (both text and textview) starting with 1 through 12, 12 being the textview.
I'm sure there are other ways to do it and this method isn't perfect, but hopefully it helps someone.
In code, I wrote the following:
func textFieldShouldReturn(textField: UITextField) -> Bool {
let nextTag = textField.tag + 1
//Handle Textview transition, Textfield programmatically
if textField.tag == 11 {
//Current tag is 11, next field is a textview
self.OtherNotes.becomeFirstResponder()
} else if nextTag > 11 {
//12 is the end, close keyboard
textField.resignFirstResponder()
} else {
//Between 1 and 11 cycle through using next button
let nextResponder = self.view.viewWithTag(nextTag) as? UITextField
nextResponder?.becomeFirstResponder()
}
return false
}
func textFieldDidEndEditing(textField: UITextField) {
textField.resignFirstResponder()
}
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
//Remove keyboard when clicking Done on keyboard
if(text == "\n") {
textView.resignFirstResponder()
return false
}
return true
}
Another approach, if you're using storyboards, you can change the textfield's attribute for Return Key.
Currently you have the following options: Default (Return), Go, Google, Join, Next, Route, Search, Send, Yahoo, Done, Emergency Call, Continue

how to add an action on UITextField return key?

I have a button and text textfield in my view. when i click on the textfield a keyboard appears and i can write on the textfield and i also able to dismiss the keyboard by clicking on the button by adding:
[self.inputText resignFirstResponder];
Now I want to enable return key of keyboard. when i will press on the keyboard keyboard will disappear and something will happen. How can I do this?
Ensure "self" subscribes to UITextFieldDelegate and initialise inputText with:
self.inputText.delegate = self;
Add the following method to "self":
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == self.inputText) {
[textField resignFirstResponder];
return NO;
}
return YES;
}
Or in Swift:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == inputText {
textField.resignFirstResponder()
return false
}
return true
}
With extension style in swift 3.0
First, set up delegate for your text field.
override func viewDidLoad() {
super.viewDidLoad()
self.inputText.delegate = self
}
Then conform to UITextFieldDelegate in your view controller's extension
extension YourViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == inputText {
textField.resignFirstResponder()
return false
}
return true
}
}
While the other answers work correctly, I prefer doing the following:
In viewDidLoad(), add
self.textField.addTarget(self, action: #selector(onReturn), for: UIControl.Event.editingDidEndOnExit)
and define the function
#IBAction func onReturn() {
self.textField.resignFirstResponder()
// do whatever you want...
}
Just add a target on textField setup function on viewDidLoad, then add its related function as selector.
override func viewDidLoad() {
super.viewDidLoad()
textField.addTarget(self, action: #selector(textFieldShouldReturn(sender:)), for: .primaryActionTriggered)
}
#objc func textFieldShouldReturn(sender: UITextField) {
textField.resignFirstResponder()
}
Use Target-Action UIKit mechanism for "primaryActionTriggered" UIEvent sent from UITextField when a keyboard done button is tapped.
textField.addTarget(self, action: Selector("actionMethodName"), for: .primaryActionTriggered)

Resources