How to toggle a UITextField secure text entry (hide password) in Swift?

I currently have a UITextfield with an eye icon in it that when pressed is supposed to toggle the secure text entry on and off.

secure text entry

I know you can check mark the "secure text entry" box in the attributes inspector but how to do it so it toggles whenever the icon is pressed?


Solution 1:

Use this code,

iconClick is bool variable, or you need other condition check it,

var iconClick = true

eye Action method:

@IBAction func iconAction(sender: AnyObject) {
        if(iconClick == true) {
            passwordTF.secureTextEntry = false
        } else {
            passwordTF.secureTextEntry = true
        }

        iconClick = !iconClick
    }

hope its helpful

Solution 2:

An unintended side-effect of this is that if the user toggles to insecure, and then back to secure, the existing text will be cleared if the user continues typing. The cursor may also end up in the wrong position unless we reset the selected text range.

Below is an implementation that handles these cases (Swift 4)

extension UITextField {
    func togglePasswordVisibility() {
        isSecureTextEntry = !isSecureTextEntry

        if let existingText = text, isSecureTextEntry {
            /* When toggling to secure text, all text will be purged if the user 
             continues typing unless we intervene. This is prevented by first 
             deleting the existing text and then recovering the original text. */
            deleteBackward()

            if let textRange = textRange(from: beginningOfDocument, to: endOfDocument) {
                replace(textRange, withText: existingText)
            }
        }

        /* Reset the selected text range since the cursor can end up in the wrong
         position after a toggle because the text might vary in width */
        if let existingSelectedTextRange = selectedTextRange {
            selectedTextRange = nil
            selectedTextRange = existingSelectedTextRange
        }
    }
}

This snippet is using the replace(_:withText:) function because it triggers the .editingChanged event, which happens to be useful in my application. Just setting text = existingText should be fine as well.

Solution 3:

Why to use an extra var. In the action method of the eye button just do as below

password.secureTextEntry = !password.secureTextEntry

UPDATE

Swift 4.2 (as per @ROC comment)

password.isSecureTextEntry.toggle()

Solution 4:

I wrote extension for the same. To provide Password toggle.

iOS password toggle eye icons

  1. In your Assets first add images that you want for toggle.

  2. Add following extension for UITextField.

    extension UITextField {
    fileprivate func setPasswordToggleImage(_ button: UIButton) {
        if(isSecureTextEntry){
            button.setImage(UIImage(named: "ic_password_visible"), for: .normal)
        }else{
            button.setImage(UIImage(named: "ic_password_invisible"), for: .normal)
    
        }
    }
    
    func enablePasswordToggle(){
        let button = UIButton(type: .custom)
        setPasswordToggleImage(button)
        button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -16, bottom: 0, right: 0)
        button.frame = CGRect(x: CGFloat(self.frame.size.width - 25), y: CGFloat(5), width: CGFloat(25), height: CGFloat(25))
        button.addTarget(self, action: #selector(self.togglePasswordView), for: .touchUpInside)
        self.rightView = button
        self.rightViewMode = .always
    }
    @IBAction func togglePasswordView(_ sender: Any) {
        self.isSecureTextEntry = !self.isSecureTextEntry
        setPasswordToggleImage(sender as! UIButton)
    }
    }
    
  3. Call extension on your UITextField Outlet

     override func viewDidLoad() {
         super.viewDidLoad()
         txtPassword.enablePasswordToggle()
         txtConfirmPassword.enablePasswordToggle()
     }
    

Solution 5:

Swift 4 solution

You don't need extra if statement for simple toggle isSecureTextEntry property

func togglePasswordVisibility() {
        password.isSecureTextEntry = !password.isSecureTextEntry
    }

But there is a problem when you toggle isSecureTextEntry UITextField doesn't recalculate text width and we have extra space to the right of the text. To avoid this you should replace text this way

func togglePasswordVisibility() {
        password.isSecureTextEntry = !password.isSecureTextEntry
        if let textRange = password.textRange(from: password.beginningOfDocument, to: password.endOfDocument) {
            password.replace(textRange, withText: password.text!)
        }
    }

UPDATE

Swift 4.2

Instead of

password.isSecureTextEntry = !password.isSecureTextEntry

you can do this

password.isSecureTextEntry.toggle()