Adding space between textfield character when typing in text filed

前端 未结 3 853
太阳男子
太阳男子 2020-12-17 07:14

I have a textfield with maximum character range 16, After every 4 characters, I want to add minus character or space and then writing The rest of the characters

相关标签:
3条回答
  • 2020-12-17 07:30

    To do it "on the fly", I connected Editing changed to this IBAction ; needs also to care for backspace

     @IBAction func editingTestField(_ sender: UITextField) {
          if sender.text!.count > 0 && sender.text!.count % 5 == 0 && sender.text!.last! != "-" {
             sender.text!.insert("-", at:sender.text!.index(sender.text!.startIndex, offsetBy: sender.text!.count-1) )
          }
     }
    
    0 讨论(0)
  • 2020-12-17 07:38

    Use shouldChangeCharactersIn like this way.

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if [6, 11, 16].contains(textField.text?.count ?? 0) && string.isEmpty {
            textField.text = String(textField.text!.dropLast())
            return true
        }
        let text = NSString(string: textField.text ?? "").replacingCharacters(in: range, with: string).replacingOccurrences(of: "-", with: "")
        if text.count >= 4 && text.count <= 16 {
            var newString = ""
            for i in stride(from: 0, to: text.count, by: 4) {
                let upperBoundIndex = i + 4
                let lowerBound = String.Index.init(encodedOffset: i)
                let upperBound = String.Index.init(encodedOffset: upperBoundIndex)
                if upperBoundIndex <= text.count  {
                    newString += String(text[lowerBound..<upperBound]) + "-"
                    if newString.count > 19 {
                       newString = String(newString.dropLast())
                    }
                }
                else if i <= text.count {
                    newString += String(text[lowerBound...])
                }
            }
            textField.text = newString
            return false
        }
        if text.count > 16 {
            return false
        }
        return true
    }
    

    Note: I have used - (Hyphen) you can simply replace it with Space if you want Space instead of - (Hyphen).

    Edit: Code is edited to latest swift 4.*, for older swift version please check edit history.

    0 讨论(0)
  • 2020-12-17 07:56

    We may start by implementing a Swift 3 version of the chunk(n:) method (for Collection's) of oisdk:s SwiftSequence:

    /* Swift 3 version of Github use oisdk:s SwiftSequence's 'chunk' method:
       https://github.com/oisdk/SwiftSequence/blob/master/Sources/ChunkWindowSplit.swift */
    extension Collection {
        public func chunk(n: IndexDistance) -> [SubSequence] {
            var res: [SubSequence] = []
            var i = startIndex
            var j: Index
            while i != endIndex {
                j = index(i, offsetBy: n, limitedBy: endIndex) ?? endIndex
                res.append(self[i..<j])
                i = j
            }
            return res
        }
    }
    

    In which case implementing your custom formatting is a simple case of creating 4-character chunks and joining these by "-":

    func customStringFormatting(of str: String) -> String {
        return str.characters.chunk(n: 4)
            .map{ String($0) }.joined(separator: "-")
    }
    

    Example usage:

    print(customStringFormatting(of: "5022222222222222")) // 5022-2222-2222-2222
    print(customStringFormatting(of: "50222222222222"))   // 5022-2222-2222-22
    print(customStringFormatting(of: "5022222"))          // 5022-222
    

    If applying to be used in the textField(_:shouldChangeCharactersIn:replacementString:) method of UITextFieldDelegate, we might want to filter out existing separators in the customStringFormatting(of:) method method, as well as implementing it as a String extension:

    extension String {
        func chunkFormatted(withChunkSize chunkSize: Int = 4, 
            withSeparator separator: Character = "-") -> String {
            return characters.filter { $0 != separator }.chunk(n: chunkSize)
                .map{ String($0) }.joined(separator: String(separator))
        }
    }
    

    And implement the controlled updating of the textfield e.g. as follows:

    let maxNumberOfCharacters = 16
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // only allow numerical characters
        guard string.characters.flatMap({ Int(String($0)) }).count ==
            string.characters.count else { return false }
    
        let text = textField.text ?? ""
    
        if string.characters.count == 0 {
            textField.text = String(text.characters.dropLast()).chunkFormatted()
        }
        else {
            let newText = String((text + string).characters
                .filter({ $0 != "-" }).prefix(maxNumberOfCharacters))
            textField.text = newText.chunkFormatted()
        }
        return false
    }
    

    The last part above will truncate possible pasted strings from the user (given that it's all numeric), e.g.

    // current 
    1234-1234-123
    
    // user paste:
    777777777
      /* ^^^^ will not be included due to truncation */  
    
    // will result in
    1234-1234-1237-7777
    
    0 讨论(0)
提交回复
热议问题