focusing a text field in swift

IosSwiftTextfield

Ios Problem Overview


I have 4 textfields on a register screen and i have it set up so that when the user presses next on each text field, the next text field is focused. Code below:

func textFieldShouldReturn(textField: UITextField) -> Bool {
    if (textField == self.fNameField) {
        textField.resignFirstResponder()
        self.sNameField.becomeFirstResponder()
    }
    else if (textField == self.sNameField) {
        self.emailField.becomeFirstResponder()
        
    } else if (textField == self.emailField) {
        self.passwordField.becomeFirstResponder()
    }
    else {
        var thereWereErrors = checkForErrors()
        if !thereWereErrors
        {
            //conditionally segue to next screen
        }
    }
    
    return true
}

On the return of the final text field, I am calling a check for errors function (below). Within that if there is an issue with any field I want to focus that text field so the user can easily correct it. What is happening is that the text field with the error is focusing (as instructed by the checkForErrors functions)for a second but then the focus is switching back to the password text field. I also tried adding in self.passwordField.resignFirstResponder() into the last else of the above function and that makes the password field lose focus but then the text field with the issue encountered is not gaining focus at all (not even for a second as before) How can I fix this?

func checkForErrors() -> Bool
{
    var errors = false
    let title = "Error"
    var message = ""
    if fNameField.text.isEmpty {
        errors = true
        message += "First name empty"
        alertWithTitle(title, message: message, ViewController: self)
        self.fNameField.becomeFirstResponder()
    }
    else if sNameField.text.isEmpty
    {
        errors = true
        message += "Surname empty"
        alertWithTitle(title, message: message, ViewController: self)
        self.sNameField.becomeFirstResponder()
    }
    else if emailField.text.isEmpty
    {
        errors = true
        message += "Email empty"
        alertWithTitle(title, message: message, ViewController: self)
        self.emailField.becomeFirstResponder()
    }
    else if !isValidEmail(emailField.text)
    {
        errors = true
        message += "Invalid Email Address"
        alertWithTitle(title, message: message, ViewController: self)
        self.emailField.becomeFirstResponder()
    }
    else if passwordField.text.isEmpty
    {
        errors = true
        message += "Password empty"
        alertWithTitle(title, message: message, ViewController: self)
        self.passwordField.becomeFirstResponder()
    }
    else if count(passwordField.text.utf16)<8
    {
        errors = true
        message += "Password must be at least 8 characters"
        alertWithTitle(title, message: message, ViewController: self)
        self.passwordField.becomeFirstResponder()
    }
    
    return errors
}

Note I have included the textField delegate.

alert with title function as requested:

func alertWithTitle(title: String!, #message: String, #ViewController: UIViewController) {
    let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    let action = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
    alert.addAction(action)
    ViewController.presentViewController(alert, animated: true, completion: nil)
}

Ios Solutions


Solution 1 - Ios

theTextFieldYouWant.becomeFirstResponder()

Solution 2 - Ios

This works for me:

import UIKit

class ViewController:UIViewController, UITextFieldDelegate {
    
    @IBOutlet weak var fNameField: UITextField!
    @IBOutlet weak var sNameField: UITextField!
    @IBOutlet weak var emailField: UITextField!
    @IBOutlet weak var passwordField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        fNameField.delegate = self
        sNameField.delegate = self
        emailField.delegate = self
        passwordField.delegate = self
    }
    
    func isValidEmail (test:String) ->Bool{
        // your email validation here...
        return true
    }
    
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        if (textField == self.fNameField) {
            self.sNameField.becomeFirstResponder()
        }
        else if (textField == self.sNameField) {
            self.emailField.becomeFirstResponder()
            
        } else if (textField == self.emailField) {
            self.passwordField.becomeFirstResponder()
        }
        else{
            var thereWereErrors = checkForErrors()
            if !thereWereErrors
            {
                //conditionally segue to next screen
            }
        }
        
        return true
    }
    
    func checkForErrors() -> Bool
    {
        var errors = false
        let title = "Error"
        var message = ""
        if fNameField.text.isEmpty {
            errors = true
            message += "First name empty"
            alertWithTitle(title, message: message, ViewController: self, toFocus:self.fNameField)

        }
        else if sNameField.text.isEmpty
        {
            errors = true
            message += "Surname empty"
            alertWithTitle(title, message: message, ViewController: self, toFocus:self.sNameField)

            self.sNameField.becomeFirstResponder()
        }
        else if emailField.text.isEmpty
        {
            errors = true
            message += "Email empty"
            alertWithTitle(title, message: message, ViewController: self, toFocus:self.emailField)

        }
        else if !isValidEmail(emailField.text)
        {
            errors = true
            message += "Invalid Email Address"
            alertWithTitle(title, message: message, ViewController: self, toFocus:self.emailField)

        }
        else if passwordField.text.isEmpty
        {
            errors = true
            message += "Password empty"
            alertWithTitle(title, message: message, ViewController: self, toFocus:passwordField)
        }
        else if count(passwordField.text.utf16)<8
        {
            errors = true
            message += "Password must be at least 8 characters"
            alertWithTitle(title, message: message, ViewController: self, toFocus:self.passwordField)
        }
        
        return errors
    }
    
    func alertWithTitle(title: String!, message: String, ViewController: UIViewController, toFocus:UITextField) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
        let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel,handler: {_ in
            toFocus.becomeFirstResponder()
        });
        alert.addAction(action)
        ViewController.presentViewController(alert, animated: true, completion:nil)
    }

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2363025View Question on Stackoverflow
Solution 1 - IosVikerView Answer on Stackoverflow
Solution 2 - IosJuan Carlos Ospina GonzalezView Answer on Stackoverflow