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
相关产品推荐
相关产品推荐

