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

UITextView设置attributedText时间歇性崩溃问题求助

解决思路

1. 将HTML解析移至后台线程,避免主队列阻塞

当前代码在主队列执行HTML解析,这是耗时操作,会挤占UI更新资源,容易导致UITextView内部缓存与UI状态不同步。应把解析逻辑放到后台队列,完成后再回到主队列更新UI:

public func attributedStringFromHTML(completionBlock: @escaping (NSAttributedString?)->()) {
    // 后台线程解析HTML
    DispatchQueue.global(qos: .userInitiated).async {
        let attributedString: NSAttributedString?
        do {
            attributedString = try NSAttributedString(data: self.customUtfData, options: [
                .documentType: NSAttributedString.DocumentType.html,
                .characterEncoding: String.Encoding.utf8.rawValue
            ], documentAttributes: nil)
        } catch {
            print("解析HTML失败: \(error)")
            attributedString = nil
        }
        // 回到主队列回调
        DispatchQueue.main.async {
            completionBlock(attributedString)
        }
    }
}

2. 避免异步回调的野指针与重复赋值

异步回调可能在UITextView所在ViewController已释放时执行,或多次调用displayTextView导致旧解析结果覆盖新内容,触发缓存冲突。可通过弱引用+取消旧任务解决:

// 存储当前解析任务,用于取消未完成的操作
private var currentParseTask: DispatchWorkItem?

func displayTextView(with text: String) {
    // 取消之前未完成的解析任务
    currentParseTask?.cancel()
    
    let task = DispatchWorkItem { [weak self] in
        text.attributedStringFromHTML { attrText in
            guard let self = self, !task.isCancelled else { return }
            // 赋值前先清空旧内容,避免新旧内容缓存冲突
            self.textView.attributedText = nil
            self.textView.attributedText = attrText
        }
    }
    currentParseTask = task
    DispatchQueue.main.async(execute: task)
}

3. 修复NSAttributedString内部结构异常

HTML解析生成的NSAttributedString可能存在内部结构不稳定,间歇性触发缓存问题。可通过重新序列化修复:

if let attributedString = try? NSAttributedString(data: self.customUtfData, options: [
    .documentType: NSAttributedString.DocumentType.html,
    .characterEncoding: String.Encoding.utf8.rawValue
], documentAttributes: nil) {
    // 重新序列化,修复内部结构
    if let data = try? attributedString.data(from: NSRange(location: 0, length: attributedString.length), documentAttributes: [.documentType: NSAttributedString.DocumentType.html]) {
        let fixedString = try? NSAttributedString(data: data, options: [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ], documentAttributes: nil)
        completionBlock(fixedString ?? attributedString)
    } else {
        completionBlock(attributedString)
    }
}

4. 检查UITextView的状态配置

  • 确保UITextView的isEditable、isSelectable等状态在赋值前保持稳定,避免在UI状态变化时执行赋值操作。
  • 若使用了自定义TextKit布局,暂时切换回系统默认布局,验证问题是否由自定义布局的缓存逻辑冲突导致。

内容的提问来源于stack exchange,提问作者toadsage

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 05:46:07