iosswiftuitextfielduitextinput

Replacing character after each type in UITextField?


I have a UITextField in which the user is expected to type a sentence which we tell the user to type. So the sentence to type is already known to us. Midway of the sentence, the user has to secretly pass a message. The way to do this is by typing a few letters of the already known sentence and then type '&' followed by WhichEverMessageUserWantsToPass and '&' to end.

The catch is the moment the user presses '&', whatever he types after that should not be displayed, instead each letter he types after that should be replaced by the letter in the already known sentence.

For example:

String - Which city did I live in 2 years ago?

User types - Which city di&Deteroit&n 2 yea

UITextField should show - Which city did I live in 2 yea

The part between the two '&' is essentially the answer by itself, so I do not want it to be shown in the text field.

My approach currently is:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    
    var addString = String(self.character[self.textLength])
    
    var start = textField.text.endIndex // Start at the string's end index as I only want the most recent character to be replaced
    var end = textField.text.endIndex // Take the string's end index as I only want one character to be changes per type
    var nextRange: Range<String.Index> = Range<String.Index>(start: start,end: end)
    
    textField.text.stringByReplacingCharactersInRange(nextRange, withString: addString)
    
    
    return true
}

However, this does not seem to replace any letter currently. Kindly help if any one knows the implementation. Thank you


Solution

  • There you go - try it out!

    let initialString = "my question to be answered"
    var inputString = NSString()
    
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        inputString = inputString.stringByReplacingCharactersInRange(range, withString: string)
    
        textField.text = inputString as String
        var range = Range<String.Index>(start: (textField.text?.startIndex)!,end: (textField.text?.endIndex)!)
    
        while true {
            if let firstIndex = textField.text!.rangeOfString("&", options: [], range: range, locale: nil) {
                range = Range<String.Index>(start: firstIndex.startIndex.successor(), end: (textField.text?.endIndex)!)
                var endIndex : String.Index?
                if let index = textField.text!.rangeOfString("&", options: [], range: range, locale: nil) {
                    endIndex = index.endIndex
                    range = Range<String.Index>(start: index.startIndex.successor(), end: (textField.text?.endIndex)!)
                } else {
                    endIndex = textField.text?.endIndex
                }
    
                let relevantRange = Range(start: firstIndex.startIndex,end: endIndex!)
                let repl = initialString.substringWithRange(relevantRange)
    
                print("would replace the \(relevantRange) with \(repl)")
    
                textField.text!.replaceRange(relevantRange, with: repl)
            } else {
                break
            }
        }
        return false
    }
    

    I think that is pretty much exactly what you wanted plus very clean, you can remove or add & mid-sentence and everything works as desired.

    Example output for the input of "&X&ghj&X&ui&X&.." would be

    would replace the 0..<3 with my
    would replace the 6..<9 with sti
    would replace the 11..<14 with to

    And the text displayed in the text-field "my ghjstiui to.." (the bold text is the one being read from the actual question and matches the &X& sections of the input.)

    Note: for swift 1 replace the [] with nil.