Swift中的ChangeCharactersInRange应该如何工作?


77

我正在使用shouldChangeCharactersInRange作为使用即时类型搜索的方式。

但是我有一个问题,在文本字段实际更新之前应该调用shouldChangeCharactersInRange

在目标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
}

在获得值之前,该方法仍会被调用?

Answers:


164

雨燕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
    }
}

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


它在键入时附加一个额外的字符,这是什么原因?
Sagar Daundkar '18

@SagarDaundkar发布您的示例文本
Vyacheslav

我说过@PrashantTukadiya
维亚切斯拉夫(Vyacheslav)

@Vyacheslav对不起任何工作围绕这个我的问题stackoverflow.com/questions/50266486/...
PRASHANT Tukadiya

@PrashantTukadiya我解决它使用一些变量,它存储了“打字”的状态
维亚切斯拉

74

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
}

3
很好奇的是我们必须转换为NSString,同时与Swift字符串一起使用,由于参数类型不同,它无法正常工作。
Hola Soy Edu Feliz Navidad 2015年

有没有不用老办法NSString
马丁

@Martin我认为,相比之下,没有那么痛苦的事情。NSString <>字符串转换远非最坏的考虑,因为它们是免费的桥接方式
bitwit

一次最多不超过2个字符
Nupur Sharma

2
不能使用几种语言(例如韩语)工作。朝鲜语单词不能仅附加最后一个字符就完成。如果输入“대한민국”,则txtAfterUpdate将为“대한민구ㄱ”。仅供韩国参考。
标记

41

斯威夫特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。在上面的代码中,这就是为什么textFieldText如果textField.text为nil(通过nil合并运算符??)设置为空字符串的原因。

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


1
确保textFieldText为NSString,否则它将引发范围错误。花了我几分钟解决。干杯。
Sharukh Mastan

为什么呢 为什么我们不能使用普通的Swift String类?
Shanakor

11

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
}

0

迅捷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


这不会覆盖现有字符而不是插入它们吗?我仍然需要尝试一下,但是afaik会在更改textField内容之前shouldChangeCharactersIn调用该方法

是的,这是正确的,但是当您true在此函数中返回时,您已经可以构造设置为文本字段的新字符串。基本上,您可以使用当前和新的文本字段内容执行所需的操作,还可以控制是否要拒绝更改,还可以控制设置的字符串。因此,您在这里拥有完全控制权。
blackjacx

0

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

看看返回的布尔值

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

-6

为了在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
}

2
如果用户删除一个字符怎么办?您必须使用范围。
加布里埃尔。马萨纳

2
如果他们在字符串中间编辑了字符怎么办?不使用范围是错误的。
迈克尔·彼得森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.