SwiftyJD
SwiftyJD

Reputation: 5441

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?

Upvotes: 86

Views: 122886

Answers (29)

JuvinR
JuvinR

Reputation: 180

Here is the updated version of Aimanzaki's answer which supports iOS 15.0 and later.

  1. Add the following extension for UITextField
extension UITextField {

    fileprivate func setPasswordToggleImage(_ button: UIButton) {
        var config = UIButton.Configuration.plain()
        if(isSecureTextEntry) {
            config.image = UIImage(systemName: "eye.slash.fill")?.withTintColor(.black, renderingMode: .alwaysOriginal)
        } else {
            config.image = UIImage(systemName: "eye.fill")?.withTintColor(.black, renderingMode: .alwaysOriginal)
        }
        config.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16)
        button.configuration = config
    }

    func enablePasswordToggle(){
        let button = UIButton(type: .custom)
        setPasswordToggleImage(button)
        button.addTarget(self, action: #selector(self.togglePasswordView), for: .touchUpInside)
        self.rightView = button
        self.rightViewMode = .always
    }

    @IBAction func togglePasswordView(_ sender: Any) {
        self.isSecureTextEntry.toggle()
        setPasswordToggleImage(sender as! UIButton)
    }
}
  1. Call the extension of your UITextField outlet in viewDidLoad()
override func viewDidLoad() {
     super.viewDidLoad()
     txtPassword.enablePasswordToggle()
 }

Upvotes: 0

Iyyappan Ravi
Iyyappan Ravi

Reputation: 3245

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 {
        passwordTF.isSecureTextEntry = false
    } else {
        passwordTF.isSecureTextEntry = true
    }
    iconClick = !iconClick
}

hope its helpful

Upvotes: 103

Naqeeb
Naqeeb

Reputation: 1421

var viewingPassword = true 

@IBAction func btnEyeAction(_ sender: Any) {
     passwordTF.isSecureTextEntry = viewingPassword ? false : true
     viewingPassword.toggle()
}

Upvotes: 0

Srinivasan_iOS
Srinivasan_iOS

Reputation: 1078

Swift 5 Please use this

var btnClick = true

if(btnClick == true) {
            passwordTextField.isSecureTextEntry = false
        } else {
            passwordTextField.isSecureTextEntry = true
        }
        
        btnClick = !btnClick

}

Upvotes: 0

Chathura Madhushanka
Chathura Madhushanka

Reputation: 71

This worked for me on Swift 5.0

@IBAction func changePasswordVisibility(_ sender: UIButton) {
    passwordField.isSecureTextEntry.toggle()
    if passwordField.isSecureTextEntry {
        if let image = UIImage(systemName: "eye.fill") {
            sender.setImage(image, for: .normal)
        }
    } else {
        if let image = UIImage(systemName: "eye.slash.fill") {
            sender.setImage(image, for: .normal)
        }
    }
}

Button attributes:

enter image description here

Result:

enter image description here enter image description here

Upvotes: 4

Aimanzaki
Aimanzaki

Reputation: 634

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()
     }
    

Upvotes: 39

Ahsan
Ahsan

Reputation: 501

 sender.isSelected = !sender.isSelected
    if(sender.isSelected == true) {
        RegPasswordField.isSecureTextEntry = false
        sender.setBackgroundImage(UIImage(systemName: "eye.fill"), for: .normal)
            } else {
                RegPasswordField.isSecureTextEntry = true
                sender.setBackgroundImage(UIImage(systemName: "eye"), for: .normal)
            }

Upvotes: 0

Muhammad Ahmad
Muhammad Ahmad

Reputation: 398

only add this line into your code replace you TextField name with "textfield" Done: you need to change the isSecureTextEntry propertity to change true for password type textFiled like ......

textField.isSecureTextEntry = true

Upvotes: 0

Sunil aruru
Sunil aruru

Reputation: 497

Hope this is simpler solution rather than creating a BOOL object globally.

@IBAction func passwordToggleButton(sender: UIButton) {
    let isSecureTextEntry = passwordTextField.isSecureTextEntry
    passwordTextField.isSecureTextEntry = isSecureTextEntry ? false : true
    if isSecureTextEntry {
        visibilityButton.setImage(UIImage(named: "visibility"), for: .normal)
    } else {
        visibilityButton.setImage(UIImage(named: "visibility_off"), for: .normal)
    }
}

Upvotes: 0

Coffee and Waffles
Coffee and Waffles

Reputation: 158

@objc func togglePasscode(){

   switch textfield.isSecureTextEntry{
      case true:
         textfield.isSecureTextEntry = false 

      case false:
         textfield.isSecureTextEntry = true 
   }
}

Here is a easy and more readable solution using Switch statement.

Upvotes: 0

Kuldeep Tanwar
Kuldeep Tanwar

Reputation: 3526

Shortest!

I think this is the shortest solution for secure entry as well as updating the picture of the button.

@IBAction func toggleSecureEntry(_ sender: UIButton) {
    sender.isSelected = !sender.isSelected
    textfieldPassword.isSecureTextEntry = !sender.isSelected
}

Assign the show/hide picture of the button according to the state selected /default , no need to create any variable or outlet.

Upvotes: 4

Phani Sai
Phani Sai

Reputation: 1233

Use UITextFiled rightView to show toggle button

 var rightButton  = UIButton(type: .custom)
 rightButton.frame = CGRect(x:0, y:0, width:30, height:30)
 yourtextfield.rightViewMode = .always
 yourtextfield.rightView = rightButton

Upvotes: 12

Pramod More
Pramod More

Reputation: 1250

Try this code in swift 4, tried to make a reusable code within a controller. I have set different image for buttons in storyboard as shown in the link https://stackoverflow.com/a/47669422/8334818

@IBAction func clickedShowPassword(_ sender: UIButton) {
        var textField :UITextField? = nil
        print("btn ",sender.isSelected.description)
        switch sender {
        case encryptOldPswdBtn:
            encryptOldPswdBtn.isSelected = !encryptOldPswdBtn.isSelected
            textField = oldPasswordTextField

        default:
          break
        }

        print("text ",textField?.isSecureTextEntry.description)
        textField?.isSecureTextEntry = !(textField?.isSecureTextEntry ?? false)

    }

Upvotes: 0

Eugene Chybisov
Eugene Chybisov

Reputation: 1704

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()

Upvotes: 25

Bishal Ghimire
Bishal Ghimire

Reputation: 2600

If you need TextField with similar feature in multiple places its best to subclass the UITextField like follwing example -

import UIKit

class UIShowHideTextField: UITextField {

    let rightButton  = UIButton(type: .custom)

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    required override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    func commonInit() {
        rightButton.setImage(UIImage(named: "password_show") , for: .normal)
        rightButton.addTarget(self, action: #selector(toggleShowHide), for: .touchUpInside)
        rightButton.frame = CGRect(x:0, y:0, width:30, height:30)

        rightViewMode = .always
        rightView = rightButton
        isSecureTextEntry = true
    }

    @objc
    func toggleShowHide(button: UIButton) {
        toggle()
    }

    func toggle() {
        isSecureTextEntry = !isSecureTextEntry
        if isSecureTextEntry {
            rightButton.setImage(UIImage(named: "password_show") , for: .normal)
        } else {
            rightButton.setImage(UIImage(named: "password_hide") , for: .normal)
        }
    }

}

After which you can use it in any ViewController,

class ViewController: UIViewController {

    @IBOutlet var textField: UIShowHideTextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        textField.becomeFirstResponder()
    }

}

Upvotes: 8

Suryakant Sharma
Suryakant Sharma

Reputation: 3960

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()

Upvotes: 54

zath
zath

Reputation: 1105

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.

Upvotes: 70

Keshav Gera
Keshav Gera

Reputation: 11244

In Swift 4

 var iconClick : Bool!

    override func viewDidLoad() {
        super.viewDidLoad()
        iconClick = true
     }


    @IBAction func showHideAction(_ sender: Any)
    {
        let userPassword = userPasswordTextFiled.text!;

        if(iconClick == true) {
            userPasswordTextFiled.isSecureTextEntry = false
            iconClick = false
        } else {
            userPasswordTextFiled.isSecureTextEntry = true
            iconClick = true
        }

}

Upvotes: 1

megaKertz
megaKertz

Reputation: 484

For Xamarin folks:

passwordField.SecureTextEntry = passwordField.SecureTextEntry ? passwordField.SecureTextEntry = false : passwordField.SecureTextEntry = true;

Upvotes: 0

singh.jitendra
singh.jitendra

Reputation: 500

First you need to set image(visible or hide) of button of eye for different state (selected or normal)

than connect IBAction and write code like

@IBAction func btnPasswordVisiblityClicked(_ sender: Any) {
        (sender as! UIButton).isSelected = !(sender as! UIButton).isSelected
        if (sender as! UIButton).isSelected {
            txtfPassword.isSecureTextEntry = false
        } else {
            txtfPassword.isSecureTextEntry = true
        }
    }

this is example of "How to set image for different state of button"

Upvotes: 1

Basir Alam
Basir Alam

Reputation: 1358

Swift 3

//    MARK: Btn EyeAction
@IBAction func btnEyeAction(_ sender: Any) {

    if(iconClick == true) {
        txtPassword.isSecureTextEntry = false
        iconClick = false
    } else {
        txtPassword.isSecureTextEntry = true
        iconClick = true
    }
}

Upvotes: 4

Christopher Larsen
Christopher Larsen

Reputation: 1411

Swift 3

passwordTF.isSecureTextEntry = true
passwordTF.isSecureTextEntry = false

Upvotes: 2

Yagnesh Dobariya
Yagnesh Dobariya

Reputation: 2251

Use button with eye image
and make buttonHandler method
set Tag for button with value 1

-(IBAction) buttonHandlerSecureText:(UIButton *)sender{
      if(sender.tag ==1){
            [self.textField setSecureTextEntry:NO];
            sender.tag = 2;
      }
      else{
            [self.textField setSecureTextEntry:YES];
            sender.tag = 1;
      }
}

Upvotes: 0

Mad Burea
Mad Burea

Reputation: 541

For Objective c

set image for RightButton In viewdidload Method

[RightButton setImage:[UIImage imageNamed:@"iconEyesOpen"] forState:UIControlStateNormal];

    [RightButton setImage:[UIImage imageNamed:@"iconEyesClose"] forState:UIControlStateSelected];

and then set action method for that RightButton

-(IBAction)RightButton:(id)sender
{

    if (_rightButton.selected)
    {

        _rightButton.selected = NO;

        _passwordText.secureTextEntry = YES;


        if (_passwordText.isFirstResponder) {
            [_passwordText resignFirstResponder];
            [_passwordText becomeFirstResponder];
        }
    }
    else
    {

      _rightButton.selected = YES;

        _passwordText.secureTextEntry = NO;

        if (_passwordText.isFirstResponder) {
            [_passwordText resignFirstResponder];
            [_passwordText becomeFirstResponder];
        }

    }
}

Upvotes: 5

iVarun
iVarun

Reputation: 6611

Here is your answer no need to take any bool var:

@IBAction func showHideAction(sender: AnyObject) {

        if tfPassword.secureTextEntry{
            tfPassword.secureTextEntry = false

        }else{
            tfPassword.secureTextEntry = true;
        } 
    }

Upvotes: 1

Bhadresh Kathiriya
Bhadresh Kathiriya

Reputation: 3244

try this line:

@IBAction func btnClick(sender: AnyObject) {
    let btn : UIButton = sender as! UIButton
    if btn.tag == 0{
        btn.tag = 1
        textFieldSecure.secureTextEntry = NO
    }
    else{
        btn.tag = 0
        textFieldSecure.secureTextEntry = NO;
    }
}

Upvotes: 1

Paulw11
Paulw11

Reputation: 114836

As others have noted, the property is secureTextEntry, but you won't find this in the UITextField documentation, as it is actually inherited by a UITextField through the UITextInputTraits protocol- https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/#//apple_ref/occ/intfp/UITextInputTraits/secureTextEntry

You can simply toggle this value each time your button is tapped:

@IBAction func togglePasswordSecurity(sender: UIButton) {
    self.passwordField.secureTextEntry = !self.passwordField.secureTextEntry
}

Upvotes: 1

Ravi Dhorajiya
Ravi Dhorajiya

Reputation: 1531

Assignment values change from YES/NO to true/false boolean values.

password.secureTextEntry = true //Visible
password.secureTextEntry = false //InVisible

You can try this code.. i think it's helpful.

Upvotes: 0

Jayesh Miruliya
Jayesh Miruliya

Reputation: 3317

@IBAction func eye_toggle_clicked(sender: AnyObject)
{
    if toggleBtn.tag == 0
    {
        passwordTxt.secureTextEntry=true
        toggleBtn.tag=1
    }
    else
    {
        passwordTxt.secureTextEntry=false
        toggleBtn.tag=0
    }
}

Upvotes: 1

Related Questions