Reputation: 447
I made a UITextField extension
to crate return button
so I can reuse for all the keyboard that don't have return button (like number pad).
What I want: I can custom the return button action to either resignFirstResponder()
or becomeFirstResponder()
in case of the textfield
is at the last or in the middle of other textfield
. In this case, I would like it to be becomeFirstResponder()
when the user tap return
to the firstNameTextField
. (note: my textfield IBOutlet
is in order)
What I get: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITextField phoneNumberShouldReturnWithSender:]: unrecognized selector sent to instance 0x7f8d07f2b6d0'
Extension
import Foundation
import UIKit
extension UITextField {
func addReturnButtonOnKeyboard(myAction: Selector?) {
let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
doneToolbar.barStyle = .default
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let next: UIBarButtonItem = UIBarButtonItem(title: "Return", style: .done, target: self, action: myAction)
let items = [flexSpace, next]
doneToolbar.items = items
doneToolbar.sizeToFit()
self.inputAccessoryView = doneToolbar
}
}
ViewController
import UIKit
import Alamofire
import IQKeyboardManagerSwift
class NewUserViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var usernameTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
@IBOutlet weak var comfirmPasswordTextField: UITextField!
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var phoneNumberTextField: UITextField!
@IBOutlet weak var firstNameTextField: UITextField!
@IBOutlet weak var lastNamePasswordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
usernameTextField.delegate = self
passwordTextField.delegate = self
comfirmPasswordTextField.delegate = self
emailTextField.delegate = self
phoneNumberTextField.delegate = self
firstNameTextField.delegate = self
lastNamePasswordTextField.delegate = self
phoneNumberTextField.addReturnButtonOnKeyboard(myAction: #selector(phoneNumberShouldReturn(sender:)))
IQKeyboardManager.shared.enableAutoToolbar = false
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let nextResponder = textField.superview?.viewWithTag(textField.tag + 1) {
nextResponder.becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return false
}
@objc func phoneNumberShouldReturn(sender: UITextField) {
firstNameTextField.becomeFirstResponder()
}
}
Thanks!!
Upvotes: 3
Views: 1746
Reputation: 258621
You specified target in extension so action is send to text field, instead of your controller, instead use like following
1) add target to interface
...
func addReturnButtonOnKeyboard(target: Any?, myAction: Selector?) {
let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
doneToolbar.barStyle = .default
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
target: nil, action: nil)
let next: UIBarButtonItem = UIBarButtonItem(title: "Return", style: .done,
target: target, action: myAction) // << here !!
...
2) pass controller as target
...
lastNamePasswordTextField.delegate = self
phoneNumberTextField.addReturnButtonOnKeyboard(target: self, // << here !!
myAction: #selector(phoneNumberShouldReturn(sender:)))
...
Upvotes: 4