Swift 5.5中UITextView文本变更时添加attributed strings的最优实现方案
Swift 5.5 下UITextView动态添加属性字符串实现方案
方案选型参考
- 若属性文本处理逻辑仅在单个页面使用,优先放在UIViewController中,无需额外封装
- 若该带属性的UITextView需要在多个页面复用,优先封装为独立UIView子类,内聚所有处理逻辑
方案1:逻辑放在UIViewController中
实现代码如下:
import UIKit class DemoViewController: UIViewController, UITextViewDelegate { private let textView = UITextView() override func viewDidLoad() { super.viewDidLoad() setupTextView() } private func setupTextView() { textView.frame = view.bounds.inset(by: UIEdgeInsets(top: 20, left: 16, bottom: 20, right: 16)) textView.font = .systemFont(ofSize: 16) textView.delegate = self view.addSubview(textView) } // 监听文本变更事件 func textViewDidChange(_ textView: UITextView) { updateAttributedText() } private func updateAttributedText() { let originalText = textView.text ?? "" let attributedString = NSMutableAttributedString(string: originalText) // 示例逻辑:给所有匹配的"高亮关键词"添加红色加粗属性 let targetKeyword = "高亮关键词" let matchRange = (originalText as NSString).range(of: targetKeyword) if matchRange.location != NSNotFound { attributedString.addAttributes([ .foregroundColor: UIColor.red, .font: UIFont.boldSystemFont(ofSize: 16) ], range: matchRange) } // 保存当前光标位置,避免赋值后光标跳转到文本末尾 let selectedRange = textView.selectedRange textView.attributedText = attributedString textView.selectedRange = selectedRange } }
注意:如果有多处匹配需求,可以用NSRegularExpression遍历所有匹配区间批量添加属性。
方案2:封装到自定义UIView中
实现代码如下:
import UIKit class AttributedTextView: UIView { private let textView = UITextView() // 对外暴露文本变更回调,供外部业务层使用 var textDidUpdate: ((String) -> Void)? override init(frame: CGRect) { super.init(frame: frame) setupUI() } required init?(coder: NSCoder) { super.init(coder: coder) setupUI() } private func setupUI() { textView.frame = bounds textView.autoresizingMask = [.flexibleWidth, .flexibleHeight] textView.font = .systemFont(ofSize: 16) textView.delegate = self addSubview(textView) } private func updateAttributedStyle() { let originText = textView.text ?? "" let attributedString = NSMutableAttributedString(string: originText) // 示例逻辑:给所有数字添加蓝色下划线属性 let numberRegex = try? NSRegularExpression(pattern: "[0-9]+", options: []) let matches = numberRegex?.matches(in: originText, options: [], range: NSRange(location: 0, length: originText.count)) ?? [] for match in matches { attributedString.addAttributes([ .foregroundColor: UIColor.blue, .underlineStyle: NSUnderlineStyle.single.rawValue ], range: match.range) } let selectedRange = textView.selectedRange textView.attributedText = attributedString textView.selectedRange = selectedRange } } extension AttributedTextView: UITextViewDelegate { func textViewDidChange(_ textView: UITextView) { updateAttributedStyle() textDidUpdate?(textView.text ?? "") } }
使用时直接在业务ViewController中初始化AttributedTextView添加到视图层级即可,所有属性处理逻辑内聚在组件内部,支持多页面复用。
内容的提问来源于stack exchange,提问作者Rob
相关产品推荐
相关产品推荐

