You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 04:45:05