Reputation: 2164
I'm new to Swift and I was creating a registration form. I have a phone text field and when I open the phone pad, I can not see the done or return button so I can dismiss the on screen keyboard with resignfirstresponder()
.
I used this link : https://gist.github.com/jplazcano87/8b5d3bc89c3578e45c3e
And now, I get the Done button but on pressing Done, my app is crashing because of the selector which says is unidentified. Can anyone please help or guide me with another way?
Thanks in advance
Here is the code
import UIKit
class ViewController: UIViewController, UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource {
@IBOutlet var registerTF: [KaustabhTF]!
// MARK:- App LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK:- User Defined
func isValidEmail(email: String) -> Bool {
let emailRegEx = "^(?:(?:(?:(?: )*(?:(?:(?:\\t| )*\\r\\n)?(?:\\t| )+))+(?: )*)|(?: )+)?(?:(?:(?:[-A-Za-z0-9!#$%&’*+/=?^_'{|}~]+(?:\\.[-A-Za-z0-9!#$%&’*+/=?^_'{|}~]+)*)|(?:\"(?:(?:(?:(?: )*(?:(?:[!#-Z^-~]|\\[|\\])|(?:\\\\(?:\\t|[ -~]))))+(?: )*)|(?: )+)\"))(?:@)(?:(?:(?:[A-Za-z0-9](?:[-A-Za-z0-9]{0,61}[A-Za-z0-9])?)(?:\\.[A-Za-z0-9](?:[-A-Za-z0-9]{0,61}[A-Za-z0-9])?)*)|(?:\\[(?:(?:(?:(?:(?:[0-9]|(?:[1-9][0-9])|(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5]))\\.){3}(?:[0-9]|(?:[1-9][0-9])|(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5]))))|(?:(?:(?: )*[!-Z^-~])*(?: )*)|(?:[Vv][0-9A-Fa-f]+\\.[-A-Za-z0-9._~!$&'()*+,;=:]+))\\])))(?:(?:(?:(?: )*(?:(?:(?:\\t| )*\\r\\n)?(?:\\t| )+))+(?: )*)|(?: )+)?$"
let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
let result = emailTest.evaluate(with: email)
return result
}
func isValidPassword(pass:String?) -> Bool {
let passwordTest = NSPredicate(format: "SELF MATCHES %@", "(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{8,}")
return passwordTest.evaluate(with: pass)
}
func displayAlert(alertMessage: String) {
let alertController = UIAlertController(title: "Alert!!", message: alertMessage, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel,handler: nil))
self.present(alertController, animated: true, completion: nil)
}
func addDoneButtonOnKeyboard()
{
let doneToolbar: UIToolbar = UIToolbar()
doneToolbar.barStyle = UIBarStyle.default
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: Selector(("doneButtonAction")))
var items = [UIBarButtonItem]()
items.append(flexSpace)
items.append(done)
doneToolbar.items = items
doneToolbar.sizeToFit()
self.registerTF[5].inputAccessoryView = doneToolbar
}
func doneButtonAction()
{
self.registerTF[5].resignFirstResponder()
}
func isValidPhone(value: String) -> Bool {
let PHONE_REGEX = "^[0-9]{10}$"
let phoneTest = NSPredicate(format: "SELF MATCHES %@", PHONE_REGEX)
let result = phoneTest.evaluate(with: value)
return result
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true) //This will hide the keyboard
}
let myPickerData = [String](arrayLiteral: "+91", "+971", "+1", "+121", "+80", "+00")
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView( _ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return myPickerData.count
}
func pickerView( _ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return myPickerData[row]
}
func pickerView( _ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
registerTF[4].text = myPickerData[row]
}
func nextTextFieldToFirstResponder(textField: KaustabhTF) {
if textField.absoluteCount() == 0
{
displayAlert(alertMessage: "Please enter the apt value.")
}
let senderTag = textField.tag
if senderTag == 0 // Name
{
registerTF[senderTag + 1].becomeFirstResponder()
}
else if senderTag == 1 // Email
{
if !isValidEmail(email: textField.text!)
{
displayAlert(alertMessage: "Please input your valid email address")
}
else
{
registerTF[senderTag + 1].becomeFirstResponder()
}
}
else if senderTag == 2 // Password
{
if !isValidPassword(pass: textField.text)
{
displayAlert(alertMessage: "Please input a password with minimum of 8 characters including an upper case character, a lower case character and a digit.")
}
else
{
registerTF[senderTag + 1].becomeFirstResponder()
}
}
else if senderTag == 3 // Confirm Password
{
if !isValidPassword(pass: textField.text)
{
displayAlert(alertMessage: "Please input a password with minimum of 8 characters including an upper case character, a lower case character and a digit.")
}
else if registerTF[senderTag-1].text != registerTF[senderTag].text
{
displayAlert(alertMessage: "Password and confirm password dont match. Please try again")
}
else
{
textField.resignFirstResponder()
}
}
else if senderTag == 4 //Country Code
{
let thePicker = UIPickerView()
registerTF[4].inputView = thePicker
thePicker.delegate = self
}
else if senderTag == 5 // Phone Number
{
self.addDoneButtonOnKeyboard()
if !isValidPhone(value: textField.text!)
{
displayAlert(alertMessage: "Please make sure that the phone number is correct")
}
doneButtonAction()
}
}
Upvotes: 3
Views: 4164
Reputation: 677
Possible Duplicate of this post: How to show "Done" button on iPhone number pad
I have tried to add a duplicate flag, However I could not do it for some reason. Hope it will be helpful for others.
Upvotes: 1
Reputation: 2201
In swift 3.0 and 4.0 you can used this code.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var txtNumber: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.addDoneButtonOnKeyboard()
}
func addDoneButtonOnKeyboard()
{
let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: 320, height: 50))
doneToolbar.barStyle = UIBarStyle.default
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(doneButtonAction))
var items = [UIBarButtonItem]()
items.append(flexSpace)
items.append(done)
doneToolbar.items = items
doneToolbar.sizeToFit()
self.txtNumber.inputAccessoryView = doneToolbar
}
**//button action generate following two way both are working great but use any one**
@objc func doneButtonAction()
{
self.txtNumber.resignFirstResponder()
}
@IBAction func doneButtonAction(_ sender: UIButton) {
self.txtNumber.resignFirstResponder()
}
}
Upvotes: 2
Reputation: 71854
Replace
Selector(("doneButtonAction"))
with
#selector(ViewController.doneButtonAction)
And complete code will be:
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(ViewController.doneButtonAction))
And add @objc
before your doneButtonAction
method and final code will be:
@objc func doneButtonAction()
{
self.registerTF[5].resignFirstResponder()
}
For more info refer THIS.
Upvotes: 2