Rob
Rob

Reputation: 2164

Done button in phone pad (Swift 4)

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

Answers (3)

Shahriar Kabir Khan
Shahriar Kabir Khan

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

Berlin
Berlin

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

Dharmesh Kheni
Dharmesh Kheni

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

Related Questions