基于 UITextField 搜索突出显示特定的 UITextView 文本 (swift2)

Highlight specific UITextView text base on UITextField search (swift2)

我有一个 UITextField 和 UIButton 来执行搜索:

@IBOutlet weak var searchcodetxt: UITextField!
@IBOutlet weak var searchcodebtn: UIButton!

按下 UIButton 时,会调用一个函数来搜索 UITextView 中 UITextFiled 中给定的单词:

@IBAction func searchcode(sender: UIButton) {
    //searchcodebtn.addTarget(self, action: "buttonPressed:", forControlEvents: .TouchUpInside)
    searchCode()
}
func searchCode(){
    let keyword = self.searchcodetxt.text
    let lowercasekeyword = keyword!.lowercaseString
    let baseString = webcode.text
    let baselowercase = baseString!.lowercaseString
    let attributed = NSMutableAttributedString(string: baseString)
    var error: NSError?
    do {
        let regex = try NSRegularExpression(pattern: lowercasekeyword, options: NSRegularExpressionOptions.CaseInsensitive)
        let matches = regex.matchesInString(baselowercase, options: [], range: NSMakeRange(0, baselowercase.characters.count))
        if let match = matches.first {
            let range = match.rangeAtIndex(1)
            if let swiftRange = rangeFromNSRange(range, forString: baselowercase) {
                attributed.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellowColor(), range: match.range)
            }
        }
        webcode.attributedText = attributed
    } catch {
        // regex was bad!
        let alertView:UIAlertView = UIAlertView()
        alertView.title = "Keywords error!"
        alertView.message = "Please use another keywords"
        alertView.delegate = self
        alertView.addButtonWithTitle("OK")
        alertView.show()
        // Delay the dismissal by 5 seconds
        let delay = 5.0 * Double(NSEC_PER_SEC)
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
        dispatch_after(time, dispatch_get_main_queue(), {
            alertView.dismissWithClickedButtonIndex(-1, animated: true)
        })
    }
}
func rangeFromNSRange(nsRange: NSRange, forString str: String) -> Range<String.Index>? {
    let fromUTF16 = str.utf16.startIndex.advancedBy(nsRange.location, limit: str.utf16.endIndex)
    let toUTF16 = fromUTF16.advancedBy(nsRange.length, limit: str.utf16.endIndex)
    if let from = String.Index(fromUTF16, within: str),
        let to = String.Index(toUTF16, within: str) {
            return from ..< to
    }
    return nil
}

但是当我点击搜索按钮时,它没有为特定单词着色。如何纠正?

您的代码需要进行一些更改才能使其正常工作。

searchCode()函数中,let range = match.rangeAtIndex(1)会因为索引越界导致应用程序崩溃。

您可以简单地使用 match.range 添加属性:

if let match = matches.first {

        attributed.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellowColor(), range: match.range)
}

只需更正此行即可使您的代码正常工作,但是这将仅突出显示文本视图中的第一个匹配项。

突出显示所有匹配项,您可以更改此块

if let match = matches.first {
        let range = match.rangeAtIndex(1)
        if let swiftRange = rangeFromNSRange(range, forString: baselowercase) {
            attributed.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellowColor(), range: match.range)
        }
    }

并在 matches 数组上添加一个循环,以遍历所有匹配项并添加一个属性以突出显示它们。

for match in matches {
    attributed.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellowColor(), range: match.range)
}

因此 完整代码 searchCode() 将是:

func searchCode(){
    let keyword = self.searchcodetxt.text
    let lowercasekeyword = keyword!.lowercaseString
    let baseString = webcode.text
    let baselowercase = baseString!.lowercaseString
    let attributed = NSMutableAttributedString(string: baseString)

    do {
        let regex = try NSRegularExpression(pattern: lowercasekeyword, options: NSRegularExpressionOptions.CaseInsensitive)
        let matches = regex.matchesInString(baselowercase, options: [], range: NSMakeRange(0, baselowercase.characters.count))

        for match in matches {
            attributed.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellowColor(), range: match.range)
        }

        webcode.attributedText = attributed
    } catch {
        // regex was bad!
        let alertView:UIAlertView = UIAlertView()
        alertView.title = "Keywords error!"
        alertView.message = "Please use another keywords"
        alertView.delegate = self
        alertView.addButtonWithTitle("OK")
        alertView.show()
        // Delay the dismissal by 5 seconds
        let delay = 5.0 * Double(NSEC_PER_SEC)
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
        dispatch_after(time, dispatch_get_main_queue(), {
            alertView.dismissWithClickedButtonIndex(-1, animated: true)
        })
    }
}

现在,您不需要 rangeFromNSRange() 方法。