Force a UITextField to lowercase while typing and retaining cursor position

≯℡__Kan透↙ 提交于 2019-12-22 10:37:55

问题


(programming in swift 2)

I have a UITextField that when the user types into it should be automatically converted to lower case WHILE typing (so NOT after form validation).

I have gotten this far:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    //only convert to lowercase for username field
    if textField == textFieldUsername {
        //let stringRange = NSRange(location: range.location, length: range.length)
        let completedString = (textField.text ?? "" as NSString).stringByReplacingCharactersInRange(range, withString: string)
        //convert the while thing to lowercase and assign back to the textfield
        textField.text = completedString.lowercaseString
        //return false to indicate that the "system" itself should not do anychanges anymore, as we did them
        return false
    }
    //return to the "system" that it can do the changes itself
    return true
}

Problem is that (1)when the user presses and holds on the UITextField to (2)move the cursor to somewhere halfway inside the string and (3)start typing that (4)the cursor jumps back to the end of the already inputted string.

Does the cursor position needs to be restored after textField: shouldChangeCharactersInRange is called maybe?


回答1:


I have taken your code and tried this.

I can replace the cursor position wherever the text is changed.

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

    let start = textField.positionFromPosition(textField.beginningOfDocument, offset:range.location)

    let cursorOffset = textField.offsetFromPosition(textField.beginningOfDocument, toPosition:start!) + string.characters.count


    textField.text = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string).lowercaseString

    let newCursorPosition = textField.positionFromPosition(textField.beginningOfDocument, offset:cursorOffset)

    let newSelectedRange = textField.textRangeFromPosition(newCursorPosition!, toPosition:newCursorPosition!)

    textField.selectedTextRange = newSelectedRange

    return false
}



回答2:


Swift 4

lowercaseString has changed to lowercased(). Also you can do this via target action instead of NotificationCenter if you prefer.

@IBOutlet fileprivate weak var textField: UITextField!

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
}

@objc func textFieldDidChange(textField: UITextField) {
    textField.text = textField.text?.lowercased()
} 



回答3:


Easier method is this.

  1. Register for the UITextFieldTextDidChangeNotification

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "textFieldDidChange:", name: UITextFieldTextDidChangeNotification, object: textField)

  2. Change the case in the notification callback.

    func textFieldDidChange(notification:NSNotification) { textField.text = textField.text?.lowercaseString }




回答4:


A solution if you are using RxSwift 4.0 :

Just call this :

emailField.rx.controlEvent(.editingChanged)
    .asObservable()
    .subscribe(self.onEditingChanged)
    .disposed(by: self.disposeBag)

With this callback :

private func onEditingChanged(event : Event<Void>){
    self.emailField.text = self.emailField.text?.lowercased()
}


来源:https://stackoverflow.com/questions/35548633/force-a-uitextfield-to-lowercase-while-typing-and-retaining-cursor-position

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!