iOS16中如何为UITextView添加正则表达式查找选项及配置参数
基于UITextView.findInteraction实现正则表达式查找
核心配置与选项处理
1. 区分默认UIAction
系统默认的查找选项(大小写敏感、全词匹配等)对应的UIAction,可通过UITextFindInteraction.ActionIdentifier枚举识别:
- 大小写敏感:
UITextFindInteraction.ActionIdentifier.caseSensitive - 全词匹配:
UITextFindInteraction.ActionIdentifier.wholeWord
在optionsMenuProvider闭包中,遍历默认菜单的子元素即可定位这些系统内置action。
2. 排除默认选项
若不需要某个默认选项,直接从action数组中移除后重新构建菜单:
textView.findInteraction?.optionsMenuProvider = { defaultMenu in var updatedActions = defaultMenu.children.compactMap { $0 as? UIAction } // 移除全词匹配选项 updatedActions.removeAll { $0.identifier == UITextFindInteraction.ActionIdentifier.wholeWord } return UIMenu(title: "", children: updatedActions) }
3. 修改默认选项状态与逻辑
如需调整默认选项的初始状态或自定义触发逻辑,可替换原action的handler:
private var currentSearchOptions: UITextSearchOptions = [] private var currentSearchText = "" // 在optionsMenuProvider中处理大小写敏感选项 if let caseSensitiveIndex = updatedActions.firstIndex(where: { $0.identifier == UITextFindInteraction.ActionIdentifier.caseSensitive }) { let originalAction = updatedActions[caseSensitiveIndex] // 保留原标识与标题,替换处理逻辑 let customCaseAction = UIAction( title: originalAction.title, image: originalAction.image, identifier: originalAction.identifier, state: .on // 设置默认开启 ) { [weak self] action in self?.currentSearchOptions.toggle(.caseInsensitive) self?.performSearch(with: self?.currentSearchText ?? "") } updatedActions[caseSensitiveIndex] = customCaseAction }
添加正则查找选项
1. 自定义正则选项Action
在optionsMenuProvider中添加正则匹配开关:
private var isRegexSearchEnabled = false // 加入自定义正则选项 let regexAction = UIAction(title: "正则匹配", state: .off) { [weak self] action in self?.isRegexSearchEnabled = action.state == .on self?.performSearch(with: self?.currentSearchText ?? "") } updatedActions.append(regexAction)
2. 实现正则查找逻辑
自定义搜索方法,根据正则开关切换查找方式:
private func performSearch(with text: String) { currentSearchText = text guard isRegexSearchEnabled, !text.isEmpty else { // 非正则模式使用系统默认查找 textView.findInteraction?.search(for: text, options: currentSearchOptions) return } // 正则查找逻辑 do { let regexOptions: NSRegularExpression.Options = currentSearchOptions.contains(.caseInsensitive) ? .caseInsensitive : [] let regex = try NSRegularExpression(pattern: text, options: regexOptions) let fullTextRange = NSRange(textView.text.startIndex..., in: textView.text) let matches = regex.matches(in: textView.text, options: [], range: fullTextRange) // 转换为系统要求的UITextFindMatch格式 let findMatches = matches.map { match in let startPos = textView.position(from: textView.beginningOfDocument, offset: match.range.location)! let endPos = textView.position(from: startPos, offset: match.range.length)! return UITextFindMatch(range: match.range, textRange: textView.textRange(from: startPos, to: endPos)!) } // 更新查找结果到findInteraction textView.findInteraction?.update(with: findMatches, for: text, options: currentSearchOptions) } catch { // 正则格式错误,返回空结果 textView.findInteraction?.update(with: [], for: text, options: currentSearchOptions) } }
关键注意点
UITextSearchOptions需自行维护,系统不会自动同步选项菜单状态,需在action的handler中手动更新。- 自定义查找后,必须调用
findInteraction?.update(with:for:options:)将结果同步到系统查找界面。 - 需处理正则表达式的格式错误,避免非法正则导致崩溃。
内容的提问来源于stack exchange,提问作者Nickkk
相关产品推荐
相关产品推荐

