如何在iOS Swift中将密码字段上的点更改为另一个字符

时间:2015-05-22 18:28:54

标签: ios swift passwords

我有一个文本字段,我想在隐藏密码时将默认点字符替换为其他字符。 有没有办法轻松做到这一点?

3 个答案:

答案 0 :(得分:3)

这里有2个选项:

  1. 使用没有安全输入选项的普通文本字段。当用户输入字符时,将其保存到字符串变量中,并在文本字段中将其替换为您要呈现的字符而不是项目符号。
  2. 这是代码(将密码显示为$$$$):

    var password: String = ""
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
    {
        password = password+string
        textField.text = textField.text+"$"
        println("\(password)")
        return false
    }
    
    1. 在此处查看答案:UITextField secureTextEntry bullets with a custom font?

答案 1 :(得分:2)

基于Ron.Kliffer的想法,我实现了可行的完整代码:

//
//  PasswordTextField.swift
//  CrifanLibSwift
//
//  Created by licrifan on 16/7/8.
//  Copyright © 2016年 licrifan. All rights reserved.
//

import UIKit

class PasswordTextField: CommonTextField, UITextFieldDelegate {
    var realText:String {
        didSet {
            print("self.text=\(self.text), realText=\(realText)")

            updateMaskStr()
        }
    }
    var maskChar:Character

    init(frame: CGRect = CGRectZero, maskChar:Character = "*") {
        print("frame=\(frame), maskChar=\(maskChar)")

        self.realText = ""
        self.maskChar = maskChar

        super.init(frame: frame)

        self.secureTextEntry = false

        self.addTarget(self, action: #selector(self.textFiledEditingChanged(_:)), forControlEvents: UIControlEvents.EditingChanged)

        self.delegate = self

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func updateMaskStr(){
        print("before update: self.text=\(self.text), self.realText=\(self.realText)")

        //change real text to mask char
        var maskStr = ""
        for _ in self.realText.characters {
            maskStr += String(self.maskChar)
        }

        self.text = maskStr

        print("after  update: self.text=\(self.text), self.realText=\(self.realText)")
    }

    func textFiledEditingChanged(textField: UITextField) {
        print("textField=\(textField), textField.text=\(textField.text)")

        updateMaskStr()
    }

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        print("textField=\(textField), range=\(range), string=\(string)")

        var allow = true
        let curText = self.realText
        let updatedStr:String = (curText as NSString).stringByReplacingCharactersInRange(range, withString: string)

        if updatedStr.characters.count > LoginRegisterPasswordLengthMax {
            print("password exceed max length \(LoginRegisterPasswordLengthMax)")
            allow = false
        }

        if allow {
            self.realText = updatedStr
        }

        print("curText=\(curText), updatedStr=\(updatedStr), self.realText=\(self.realText)")

        return false
    }
}

并在另一个视图EditInfoView.swift中使用它:

class EditInfoView: UIView {

    var passwordTextField:PasswordTextField

    init(editMode:EditInfoMode) {

        self.passwordTextField = PasswordTextField()

        self.addSubview(self.passwordTextField)

        if self.passwordTextField.notHidden {
            //5. password text
            var passwordPlaceholder = "密码(6-20位)"
            if self.editMode == .ChangeLoginPassword {
                passwordPlaceholder = "旧密码(6-20位)"
            } else if self.editMode == .ForgotPassword {
                passwordPlaceholder = "输入新密码(6-20位)"
            }

            self.passwordTextField.placeholder = passwordPlaceholder
            self.passwordTextField.returnKeyType = UIReturnKeyType.Go
//            self.passwordTextField.secureTextEntry = true
            constrain(passwordTextField, smsCodeTextField, phoneTextField) {passwordTextField, smsCodeTextField, phoneTextField in
                passwordTextField.centerX == passwordTextField.superview!.centerX
                passwordTextField.width == passwordTextField.superview!.width - 2 * LoginRegisterPaddingX
                passwordTextField.height == CommonTextFieldHeight

                if self.editMode == .ChangeLoginPassword {
                    passwordTextField.top == passwordTextField.superview!.top + EditInfoViewTopPadding
                } else {
                    passwordTextField.top == smsCodeTextField.bottom + EditInfoViewCommonPaddingY
                }
            }
        }
}

最终在视图控制器EditInfoViewController.swift中实际使用它:

isValid = validatePassword(self, alertPrefix: alertPrefix, passwordStr: self.editInfoView.passwordTextField.realText, doAlertWhenInvalid: doAlertWhenInvalid)

最终效果是:

enter image description here

答案 2 :(得分:0)

Swift 5 可供使用, crifan 的更新版本:

import UIKit

class PasswordTextField: UITextField, UITextFieldDelegate {
    var realText: String {
        didSet {
            updateMaskStr()
        }
    }
    let maskChar: Character
    
    init(
        frame: CGRect = .zero,
        maskChar: Character = "*"
    ) {
        realText = ""
        self.maskChar = maskChar
        super.init(frame: frame)
        setupActions()
        setupDelegates()
    }
    
    private func setupActions() {
        addTarget(self, action: #selector(textFiledEditingChanged(textField:)), for: .editingChanged)
    }
    
    private func setupDelegates() {
        delegate = self
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func updateMaskStr(){
        //change real text to mask char
        var maskStr = ""
        
        for _ in realText {
            maskStr += String(self.maskChar)
        }
        
        text = maskStr
    }
    
    @objc
    private func textFiledEditingChanged(textField: UITextField) { updateMaskStr() }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let curText = realText
        let updatedStr:String = (curText as NSString).replacingCharacters(in: range, with: string)
        realText = updatedStr
        return false
    }
}