Implementing Regex in iOS

  • 原文http://www.cocoachina.com/ios/20150415/11568.html

既然你有了这些基础,就在APP中应用正则表达式吧。

如果你还没有这样做,下载 starter project 开始本教程吧。下载下来,用Xcode打开并运行它。

APP的UI部分已经完成了大部分,但这个APP的核心功能依赖与正则表达式,这个还没有…!你的任务就是添加正则表达式来时这个APP更出色。

下面所视的几个截图的例子展示了这个应用的内容:


Implementing Regex in iOS_第1张图片
1428995296861821.png

这个简单的应用涵盖两个正则表达式的通用用例:
1.执行搜索:高亮显示搜索和替换
2.验证用户输入

这就开始直接使用正则表达式:文本搜索

  • /Search( and replace)?/

这是一个搜索/替换的简单功能的概述:

搜索视图控制器SearchViewController 有一个只读的UITextView,其内容是《傲慢与偏见》的一个片段。
navigation bar包含一个搜索按钮,点击会呈现一个模态的SearchOptionsViewController。
用户输入一些信息并点击“Search”按钮。
APP会隐藏这个search view 并高亮显示textview中所有匹配的内容。
如果用户选择了SearchOptionsViewController中的“Replace”选项,APP会执行搜索并替换文本中所有匹配的内容,不再是高亮显示结果。
Note:你的APP会用到UITextView的NSAttributedString属性来高亮显示搜索的结果。更多这方面的内容请参考 iOS 6 by Tutorials的第15章--“What’s New with Attributed Strings”。

你也可以用text kit来实现高亮的功能。确保找到Text Kit Tutorial in Swift 来查看更多内容。

还有一个“Bookmark”按钮,允许用户高亮显示文本中的日期,时间,位置。为简单起见,不会涵盖文本中出现的各种格式的日期时间位置。在教程的结尾你可以实现这个高亮功能。

开始实现这个功能的第一步是跳转到标准字符串正则表达式的NSRegularExpression对象。

打开SearchOptionsViewController.swift。SearchViewController模态显示这个view controller,且允许用户键入他们的搜索条件,也可以指定是否区分大小写。

看一下文件头部的SearchOptions结构体,SearchOptions是一个封装了用户搜索选项的简答结构体。代码传递SearchOptions的一个实例给SearchViewController。它用这种方式很好的构造一个合适的NSRegularExpression,你可以通过运用扩展自定义的NSRegularExpression来实现。

选择File > New > File… 选择Swift File,命名为RegexHelpers.swift。打开新建的文件并添加如下代码:

extension NSRegularExpression {
  convenience init?(options: SearchOptions) {
    let searchString = options.searchString
    let isCaseSensitive = options.matchCase
    let isWholeWords = options.wholeWords
  
    let regexOption: NSRegularExpressionOptions = (isCaseSensitive) ? .allZeros : .CaseInsensitive
  
    let pattern = (isWholeWords) ? "\\b\(searchString)\\b" : searchString
  
    self.init(pattern: pattern, options: regexOption, error: nil)
  }
}

代码为NSRegularExpression增加了一个便利构造方法。它通过SearchOptions实例的不同设置来做一些正确的配置。

当用户请求一个不区分大小写的搜索,正则表达式使用.CaseInsensitive的CaseInsensitiveNSRegularExpressionOptions值。NSRegularExpression默认是区分大小写的,这个例子中,你使用的是更有好的不区分大小写。
如果用户请求一个完整的单词,APP把正则表达式包含在\b字符组之内。在单词边界字符组中放入\b,因此,搜索模式之前和之后加上\b就会返回一个完整的单词搜索(举例来说,模式“\bcat\b”只会匹配单词“cat”,而不会匹配“catch”)。
如果以任何理由都不能创建NSRegularExpression,构造函数就会失败并返回nil。既然你有了NSRegularExpression对象,你就能伴随着其他操作来匹配文本了。

打开SearchViewController.swift,找到searchForText,用下面的代码替换它。

func searchForText(searchText: String, replaceWith replacementText: String, inTextView textView: UITextView) {
  let beforeText = textView.text
  let range = NSMakeRange(0, countElements(beforeText))
  
  if let regex = NSRegularExpression(options: self.searchOptions!) {
    let afterText = regex.stringByReplacingMatchesInString(beforeText, options: .allZeros, range: range, withTemplate: replacementText)
  
    textView.text = afterText
  }
}

首先,这个方法捕获UITextView中得当前文本,并计算文本的长度。可能会把正则表达式应用在文本的一个子集上,所以你需要指定一个范围。这种情况下,你要用字符串的整个长度才能保证正则表达式被运用在整个文本上。

不可思议的事发生在调用stringByReplacingMatchesInString的时候。这个方法返回一个新字符串并没有改变旧字符串。然后,这个方法给UITextView设置这个新字符串,所以用户看到了正确的结果。

继续留在SearchViewController,找到highlightText,用下面的代码替换它。

func highlightText(searchText: String, inTextView textView: UITextView) {
  // 1 
  let attributedText = textView.attributedText.mutableCopy() as NSMutableAttributedString
  // 2
  let attributedTextRange = NSMakeRange(0, attributedText.length)
  attributedText.removeAttribute(NSBackgroundColorAttributeName, range: attributedTextRange)
  // 3
  if let regex = NSRegularExpression(options: self.searchOptions!) {
    let range = NSMakeRange(0, countElements(textView.text))
    let matches = regex.matchesInString(textView.text, options: .allZeros, range: range)
   // 4
    for match in matches as [NSTextCheckingResult] {
      let matchRange = match.range
  
      attributedText.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellowColor(), range: matchRange)
    }
  }
  // 5
  textView.attributedText = attributedText.copy() as NSAttributedString
}

这儿就一步一步的解释上面的代码:

1.首先,得到一个textview的attributedText的可变拷贝,

2.然后,创建一个整个文本长度的NSRange,并删除已经有背景色的文本的背景色,

3.正如找到和替换,紧接着用你的便利构造方法创建一个正则表达式,获取一个存放正则表达式与textview中文本匹配的所有匹配项的数组。

  1. 轮询每一个匹配项(把它们转换成NSTextCheckingResult对象),并为每一项添加黄色背景。

5.最后,用高亮的结果更新UITextView。

编译和运行你的APP,试着搜索一些不同的单词和词组!整个文本的匹配项都会高亮显示,就像下面的图片所示:

Implementing Regex in iOS_第2张图片
1428995793122575.png

试着使用不同的选项(options)搜索单词“the”看看效果。注意,例如,当搜索整个单词时,‘them’中得‘the’不会高亮显示。
再者,测试一下搜索和替换功能,看看你的文本字符串是怎样如期替换的,试一下’match case‘和‘whole words’选项。

你可能感兴趣的:(Implementing Regex in iOS)