【问题标题】:How shouldChangeCharactersInRange works in Swift?shouldChangeCharactersInRange 如何在 Swift 中工作?
【发布时间】:2014-10-26 14:33:57
【问题描述】:

我正在使用 shouldChangeCharactersInRange 作为使用动态类型搜索的一种方式。

但是我遇到了一个问题,shouldChangeCharactersInRange 在文本字段实际更新之前被调用:

在 Objective C 中,我使用以下方法解决了这个问题:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];

    return YES;
}

但是,我尝试用 Swift 编写这个:

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
    let txtAfterUpdate:NSString = self.projectSearchTxtFld.text as NSString
    txtAfterUpdate.stringByReplacingCharactersInRange(range, withString: string)

    self.callMyMethod(txtAfterUpdate)
    return true
}

在我得到一个值之前该方法仍然被调用?

【问题讨论】:

    标签: ios objective-c swift uitextfielddelegate nsrange


    【解决方案1】:

    stringByReplacingCharactersInRange 返回一个新的字符串,那么如何:

    func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
        if let text = textField.text as NSString? {
            let txtAfterUpdate = text.replacingCharacters(in: range, with: string)
            self.callMyMethod(txtAfterUpdate)
        }
        return true
    }
    

    【讨论】:

    • 这很奇怪,我们必须转换为 NSString,同时使用 Swift 字符串,由于参数类型不同,它不起作用。
    • 不使用旧的NSString的任何方式?
    • @Martin 我认为没有比这更痛苦的了。 NSString 字符串转换远不是最糟糕的,因为它们是免费桥接的
    • 一次不超过2个字符
    • 不适用于韩语等少数语言。仅添加最后一个字符并不能完成韩语单词。如果输入“대한민국”,txtAfterUpdate 将是“대한민구ㄱ”。仅供韩国人参考。
    【解决方案2】:

    斯威夫特 3 & 4

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let textFieldText: NSString = (textField.text ?? "") as NSString
        let txtAfterUpdate = textFieldText.replacingCharacters(in: range, with: string)
        callMyMethod(txtAfterUpdate)
    
        return true
    }
    
    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        callMyMethod("")
        return true
    }
    

    斯威夫特 2.2

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        let textFieldText: NSString = textField.text ?? ""
        let txtAfterUpdate = textFieldText.stringByReplacingCharactersInRange(range, withString: string)
        callMyMethod(txtAfterUpdate)
    
        return true
    }
    
    func textFieldShouldClear(textField: UITextField) -> Bool {
        callMyMethod("")
        return true
    }
    

    虽然textField.text 属性是可选的,但它不能设置为nil。将其设置为 nil 将更改为 UITextField 内的空字符串。在上面的代码中,如果 textField.text 为 nil(通过 nil 合并运算符 ??),这就是为什么 textFieldText 设置为空字符串的原因。

    实现textFieldShouldClear(_:) 处理文本字段的清除按钮可见并被点击的情况。

    【讨论】:

    • 确保 textFieldText 是 NSString,否则会抛出范围错误。我花了几分钟来解决。干杯。
    • 为什么?为什么我们不能使用普通的 Swift String 类?
    【解决方案3】:

    Swift 3 中它看起来像这样:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let text: NSString = (textField.text ?? "") as NSString
        let resultString = text.replacingCharacters(in: range, with: string)
    
        return true
    }
    

    【讨论】:

    • 完美!!谢谢
    【解决方案4】:

    为了在 Swift 3.0 中的 UITextField 组件中获取准确的文本,我使用了:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
       let enteredTxt = textField.text! + string
       doSomethingWithTxt(enteredTxt) //some custom method
    }
    

    【讨论】:

    • 如果用户要删除一个字符怎么办?您必须使用范围。
    • 如果他们在字符串中间编辑字符怎么办?不使用范围是错误的。
    【解决方案5】:

    斯威夫特 3


    如果你想预处理用户输入或粘贴的字符,下面的解决方案就像一个魅力

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
        let strippedString = <change replacements string so it fits your requirement - strip, trim, etc>
    
        // replace current content with stripped content
        if let replaceStart = textField.position(from: textField.beginningOfDocument, offset: range.location),
            let replaceEnd = textField.position(from: replaceStart, offset: range.length),
            let textRange = textField.textRange(from: replaceStart, to: replaceEnd) {
    
            textField.replace(textRange, withText: strippedString)
        }
        return false
    }
    

    在这里找到它:https://gist.github.com/Blackjacx/2198d86442ec9b9b05c0801f4e392047

    【讨论】:

    • 这不会覆盖现有字符而不是插入它们吗?我仍然需要尝试一下,但是 shouldChangeCharactersIn 方法被调用之前 textField 内容被更改
    • 是的,这是真的,但是当您在此函数中返回 true 时,您已经可以构造设置为文本字段的新字符串。基本上你可以对当前和新的文本字段内容做你想做的事情,加上你可以控制是否要拒绝更改加上你可以修改设置的字符串。因此,您可以完全控制这里。
    【解决方案6】:

    斯威夫特 4、斯威夫特 5

    此方法不使用NSString

    // MARK: - UITextFieldDelegate
    
    extension MyViewController: UITextFieldDelegate {
        func textField(_ textField: UITextField,
                       shouldChangeCharactersIn range: NSRange,
                       replacementString string: String) -> Bool {
            if let text = textField.text,
               let textRange = Range(range, in: text) {
               let updatedText = text.replacingCharacters(in: textRange,
                                                           with: string)
               myvalidator(text: updatedText)
            }
            return true
        }
    }
    

    注意。使用安全文本字段时要小心。

    【讨论】:

    • 打字的时候多了一个字符,是什么原因?
    • @SagarDaundkar 发布您的示例文本
    • @PrashantTukadiya 我说过了
    • @Vyacheslav 抱歉我的问题有任何解决方法stackoverflow.com/questions/50266486/…
    • @PrashantTukadiya 我使用一些存储“打字”状态的变量解决了这个问题
    【解决方案7】:

    当进行了更改但 UI 未更新并等待您的选择时调用此函数

    看看返回的布尔值

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
    
    • 如果您返回 true - 表示 iOS 接受更改(文本、插入符号...)
    • 如果您返回false - 这意味着您应对所有这些事情负责

    【讨论】:

      【解决方案8】:

      每次按键都会调用shouldChangeCharactersIn

      func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
          // get the current text, or use an empty string if that failed
          let currentText = textField.text ?? ""
      
          // attempt to read the range they are trying to change, or exit if we can't
          guard let stringRange = Range(range, in: currentText) else { return false }
      
          // add their new text to the existing text
          let updatedText = currentText.replacingCharacters(in: stringRange, with: string)
      
          // make sure the result is under 16 characters
          return updatedText.count <= 16
      }
      

      【讨论】:

      猜你喜欢
      • 2017-02-02
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 2017-04-01
      • 2015-04-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多