【问题标题】:Force a UITextField to lowercase while typing and retaining cursor position在键入和保留光标位置时强制 UITextField 为小写
【发布时间】:2018-07-11 14:48:17
【问题描述】:

(在 swift 2 中编程)

我有一个 UITextField,当用户输入它时,它应该在输入时自动转换为小写(所以不是在表单验证之后)。

我已经走到这一步了:

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
}

问题在于 (1) 当用户按住 UITextField 以 (2) 将光标移动到字符串中间的某个位置并 (3) 开始输入 (4) 光标跳回已经输入了字符串。

textField: shouldChangeCharactersInRange 调用后是否需要恢复光标位置?

【问题讨论】:

标签: ios swift2 xcode7


【解决方案1】:

我已经使用了你的代码并尝试了这个。

我可以在文本发生变化的地方替换光标位置。

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
}

【讨论】:

  • 虽然@Pradeep K 提到了最简单的方法,但我改进了你的代码,因为你已经有了它。正如 Pradeep K 提到的那样
  • 在 shouldChangeCharactersInRange 委托回调中更改文本不是一个好习惯。根据您尝试做的事情,您会得到意想不到的结果。此委托应仅用于检查范围内的字符是否可以更改。但实际文本应该在 UITextFieldDidChangeNotification 中更改。
【解决方案2】:

斯威夫特 4

小写字符串已更改为小写()。如果您愿意,也可以通过目标操作而不是 NotificationCenter 来执行此操作。

@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】:

    更简单的方法是这个。

    1. 注册 UITextFieldTextDidChangeNotification

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

    2. 在通知回调中更改大小写。

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

    【讨论】:

    • 最佳解决方案。谢谢!
    【解决方案4】:

    如果您使用的是 RxSwift 4.0 的解决方案:

    就这样称呼吧:

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

    有了这个回调:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-18
      • 1970-01-01
      • 2010-12-02
      • 2015-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      相关资源
      最近更新 更多