Ios 在UITextView中跟踪并更改文本的颜色

Ios 在UITextView中跟踪并更改文本的颜色,ios,swift,string,uitextview,Ios,Swift,String,Uitextview,当用户在文本视图中输入时,我查看每个单词,并看到它与我拥有的数组中的单词相匹配。如果存在匹配项,则单词将更改为蓝色,布尔变量didFindACertainWord将设置为true(以确保只有一个单词为蓝色)。我成功地完成了这一部分,但出现了一些错误: 我改成蓝色的某个单词可以工作,但在字体之前键入的单词会被更改,而在该单词之后键入的任何内容也都是蓝色的(我不想要)我只想将某个单词改为蓝色,其他单词保持黑色,字体与以前相同。 我不知道如何找出用户是否删除了某个单词。如果他们这样做,我想将特定单词的

当用户在文本视图中输入时,我查看每个单词,并看到它与我拥有的数组中的单词相匹配。如果存在匹配项,则单词将更改为蓝色,布尔变量
didFindACertainWord
将设置为true(以确保只有一个单词为蓝色)。我成功地完成了这一部分,但出现了一些错误:

  • 我改成蓝色的某个单词可以工作,但在字体之前键入的单词会被更改,而在该单词之后键入的任何内容也都是蓝色的(我不想要)我只想将某个单词改为蓝色,其他单词保持黑色,字体与以前相同。

  • 我不知道如何找出用户是否删除了某个单词。如果他们这样做,我想将特定单词的颜色改回黑色(在他们删除了特定单词的第一个字符后),并将
    didFindACertainWord
    设置为false。

  • 以下是我的
    textViewDidChange
    方法中的当前代码:

    func textViewDidChange(_ textView: UITextView) {
        //get last word typed
        let size = textView.text.reversed().firstIndex(of: " ") ?? textView.text.count
        let startWord = textView.text.index(textView.text.endIndex, offsetBy: -size)
        let lastWord = textView.text[startWord...]
    
        //check if last word is in array and we did not already find one
        if certainWords.contains(String(lastWord)) && !didFindACertainWord {
            didFindACertainWord = true
    
            //change color of the word
            let attributedString = NSMutableAttributedString.init(string: textView.text)
            let range = (textView.text as NSString).range(of: String(lastWord))
            attributedString.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.blue, NSAttributedString.Key.font: UIFont(name: "Avenir-Roman", size: 18)], range: range)
            textView.attributedText = attributedString
        }
    }
    
    我遗漏了什么/如何才能成功做到这一点?注意:文本视图中所有文本的字体应为
    UIFont(名称:“Avenir Roman”,大小:18)


    我正在搜索每个单词,因为在用户键入一个动作词之后,如果下一个单词与动作词相关,我需要阅读它们以加粗。例如,如果用户键入“see Paris-London-Berlin to find the best food”,动作词是“see”,相关词粗体是“Paris-Italy-France”,而不相关的词(将使用常规字体)是“to find the best”

    对于第一期,这是因为您应该使用“else”案例,并重置颜色和布尔值。 您应该添加:

    } else {
        didFindACertainWord = false
        textView.attributedText = attributedString
    }
    
    对于第二个,您不需要只处理最后一个单词,而是检查整个字符串中是否有匹配项

    未经测试,但应适用于工程:

    func textViewDidChange(_ textView: UITextView) {
    
        let attributedString = NSMutableAttributedString(string: textView.text,
                                                         attributes: [.font: UIFont(name: "Avenir-Roman", size: 18)])
    
        let allWords = attributedString.string.components(separatedBy: CharacterSet.whitespaces)
        if let firstMatch = allWords.first(where: { return certainWords.contains($0)}) {
            didFindACertainWord = true
            let firstMatchRange = (attributedString.string as NSString).range(of: firstMatch)
            attributedString.addAttribute(.foregroundColor, value: UIColor.blue, range: firstMatchRange)
        } else {
            didFindACertainWord = false
        }
        textView.attributedText = attributedString
    }
    

    对于第一个问题,这是因为您应该执行“else”情况,并重置颜色和布尔值。对于第二个,您不需要继续只处理最后一个单词,而是检查整个字符串中是否有匹配项。如果让firstMatch=allWords.first(其中:containswarks($0)),则行
    {
    如果给我错误,请在您的回答中回答。错误指向未识别的
    containsWivers
    。当我第一次遇到此错误时,我假设您试图引用我正在查找的单词数组,因此我将其更改为
    certainWords
    。一旦我这样做,错误现在是:“匿名闭包参数未包含在闭包中”。我不确定这意味着什么,也不知道如何修复它。
    …其中:certainWords(contains:$0).
    取而代之的是?太好了!它起了作用。你是否知道一种聪明的方法,可以在用户键入动作词后检查这些词是否相关(在我文章的最后一段中)找到单词后,可以使用
    range(of:options:range:)
    (如果仍要使用
    NSString
    而不是
    String
    ),搜索任何内容,但在动作单词之后(或之前),
    range
    参数允许您这样做。