簡體   English   中英

Swift 5 - 用 X 屏蔽文本字段文本

[英]Swift 5 - Mask Textfield Text with X

我想要實現的是,TextField 格式應該是 XXXX XXXX XXXX 當用戶點擊顯示按鈕它應該顯示文本 1234 5678 9123

下面是我能夠實現 1234 5678 9123 格式的代碼,屏蔽和存儲原始數據待定。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
{
        if textField.tag == 0 || textField.tag == 1 {
        if string.isBackspace
        {
            if range.location == 5 || range.location == 10
            {
                textField.text?.removeLast()
            }
        }
        
        if string == ""{
            return true
        }

        //range.length will be greater than 0 if user is deleting text - allow it to replace
        if range.length > 0
        {
            return true
        }

        //Don't allow empty strings
        if string == " "
        {
            return false
        }

        //Check for max length including the spacers we added
        if range.location > 13 //23
        {
            return false
        }

        var originalText = textField.text
        let replacementText = string.replacingOccurrences(of: " ", with: "")

        //Verify entered text is a numeric value
        let digits = NSCharacterSet.decimalDigits
        for char in replacementText.unicodeScalars
        {
            if !(digits as NSCharacterSet).longCharacterIsMember(char.value)
            {
                return false
            }
        }
        //Put an empty space after every 4 places
        if (originalText?.count)! > 0
        {
            if (originalText?.count)! < 5 && (originalText?.count)! % 4 == 0{
                originalText?.append(" ")
            }else if(((originalText?.count)! + 1) % 5 == 0){
                originalText?.append(" ")
            }

        }

        textField.text = originalText
        }
        
        //2 - Nick Name,3 - Recipient Name
        if textField.tag == 2 || textField.tag == 3 {
            //Max Limit for Nick Name and Benificiary Name is 65
            if range.location > 64
            {
                return false
            }
        }
        return true
    }

如果我理解正確,您的要求是創建一個自定義安全文本字段。 要求是:

  • 用戶最多可輸入 12 個符號
  • 只允許數字
  • 文本字段可能具有“屏蔽”和“正常”模式
  • 顯示的文本應通過將 4 個字符組合在一起來格式化
  • 每組之間有一個空格
  • 在“屏蔽”模式下,所有數字都替換為“X”符號
  • 在正常模式下,數字是可見的

此外,所有文本字段功能都可以正常工作,包括復制粘貼、選擇、在文本中間插入代碼……

我創建了一個新項目並很快以這個結束:

class ViewController: UIViewController {
    
    @IBOutlet private var textField: UITextField?
    
    private var actualText: String = ""
    private var maskedText: String = ""
    
    private var masked: Bool = true {
        didSet {
            refreshTextField()
        }
    }
    
    @IBAction private func maskedTogglePressed(_ sender: Any) {
        masked = !masked
    }
    
    private func refreshTextField() {
        textField?.text = masked ? maskedText : actualText
    }
}

extension ViewController: UITextFieldDelegate {
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        var newString = (actualText as NSString).replacingCharacters(in: range, with: string) // Apply new text
        
        // Remove all whitespaces
        newString = newString.replacingOccurrences(of: " ", with: "")
        // Remove all that is not a number
        newString = newString.filter("0123456789".contains)
        
        // Split string into components of max 4
        var components: [String] = {
            var toDeplete = newString
            var components: [String] = []
            while !toDeplete.isEmpty {
                let length = min(toDeplete.count, 4)
                components.append(String(toDeplete.prefix(length)))
                toDeplete.removeFirst(length)
            }
            return components
        }()
        // Limit to maximum of 3 components
        if components.count > 3 {
            components = Array(components[0..<3])
        }
        
        // Generate masked components, replacing all characters with X
        let maskedComponents: [String] = components.map { String($0.map { character in return "X" }) }
        
        // Add spaces
        newString = components.joined(separator: " ")
        let maskedText = maskedComponents.joined(separator: " ")
        
        // Assign new strings
        self.actualText = newString
        self.maskedText = maskedText
        
        // Refresh field
        refreshTextField()
        
        // Disallow text field to apply it's change
        return false
    }
    
}

在處理字符串時可以使用一些改進。 但它完成了這項工作。

對代碼進行了注釋,並應提供有關解決方案的更多信息。

最后我能夠解決這個問題,這是 Adwait Barkale 的解決方案。 有任何疑問給我發郵件 adwaitbarkale@gmail.com

注意:- arrPersonalDetails[2].value 只是一個字符串(使用要存儲輸入的原始文本的變量)

1.UITextfield代表

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
    {
        if textField.tag == 0 || textField.tag == 1 {
            //For Masking Numbers 1234 5678 9123 into XXXX XXXX XXXX
            //1.Storing original data 1234 5678 9123 into arrPersonalDetails[index].value
            //2.Formatting textfield by putting spaces after every 4 and 8 digit
            
            //Step 1 Store Data Locally
            if string.isBackspace
            {
                if range.location == 5 || range.location == 10
                {
                    textField.text?.removeLast()
                }
                if arrPersonalDetails[textField.tag].value!.count == 11 || arrPersonalDetails[textField.tag].value!.count == 6
                {
                    arrPersonalDetails[textField.tag].value!.removeLast()
                }
            }
            //Check for max length including the spacers we added
            if range.location > 13 //23
            {
                return false
            }
            
            if string.isBackspace
            {
                if arrPersonalDetails[textField.tag].value!.count != 0 && arrPersonalDetails[textField.tag].value!.count != 11 || arrPersonalDetails[textField.tag].value!.count != 0 && arrPersonalDetails[textField.tag].value!.count != 6
                {
                    let truncated = String(arrPersonalDetails[textField.tag].value!.dropLast())
                    arrPersonalDetails[textField.tag].value = truncated
                }
            } else {
                if arrPersonalDetails[textField.tag].value!.count == 4 || arrPersonalDetails[textField.tag].value!.count == 9
                {
                    arrPersonalDetails[textField.tag].value!.append(" ")
                }
                arrPersonalDetails[textField.tag].value!.append(string)
            }
            let oValue = arrPersonalDetails[textField.tag].value
            arrPersonalDetails[textField.tag].value = oValue
            
            if string == ""{
                return true
            }
            
            //range.length will be greater than 0 if user is deleting text - allow it to replace
            if range.length > 0
            {
                return true
            }
            
            //Don't allow empty strings
            if string == " "
            {
                return false
            }
            
            //Step 2 - Manage Textfield Data
            var originalText = textField.text
            let replacementText = string.replacingOccurrences(of: " ", with: "")
            
            //Verify entered text is a numeric value
            let digits = NSCharacterSet.decimalDigits
            for char in replacementText.unicodeScalars
            {
                if !(digits as NSCharacterSet).longCharacterIsMember(char.value)
                {
                    return false
                }
            }
            //Put an empty space after every 4 places
            if (originalText?.count)! > 0
            {
                if (originalText?.count)! < 5 && (originalText?.count)! % 4 == 0{
                    originalText?.append(" ")
                }else if(((originalText?.count)! + 1) % 5 == 0){
                    originalText?.append(" ")
                }
                
            }
            textField.text = originalText
        }
        return true
    }

2.將目標添加到文本字段

cell.tflData.addTarget(self, action: #selector(maskTextfield(tfl:)), for: .editingChanged)

/// Function to mask unmask textfiel's text
    /// - Parameter tfl: UITextfield
    @objc func maskTextfield(tfl: UITextField)
    {
        let value = arrPersonalDetails[tfl.tag].value
        if showOriginalText //Change this value on your button click
        {
            tfl.text = value
        } else {
            //Masking numbers with X
            var maskedText = ""
            if value!.count != 0 {
            for i in 1...value!.count {
                if i == 5 || i == 10 {
                    maskedText.append(" ")
                } else {
                    maskedText.append("X")
                }
            }
            }
            print("Masked Text = \(maskedText)")
            tfl.text = maskedText
        }
    }

編輯:-

注意:- 在 Textfield 中沒有結束編輯不要寫 someVariable = textField.text 否則它將需要 XXXX XXXX XXXX

而是寫這個,

func textFieldDidEndEditing(_ textField: UITextField) {
        //Bank Account textfield
        if textField.tag == 2
        {
            self.arrPersonalDetails[2].value = self.arrPersonalDetails[2].value
        }
        //Re-enter Bank Account textfield
        if textField.tag == 3
        {
            self.arrPersonalDetails[3].value = self.arrPersonalDetails[3].value
        }
    }

快樂編碼!!!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM