HTML字符串转AttributedString出现内存泄漏,求替代方案
HTML转AttributedString内存泄漏的替代解决方案
针对你遇到的系统HTML解析API内存泄漏问题,这里提供几个可行的替代方案:
方案一:优化原实现,复用解析配置
将解析用的options字典改为静态常量,避免每次调用时重复创建,减少内存分配风险:
extension String { // 全局复用的解析配置,仅初始化一次 private static let htmlParseOptions: [NSAttributedString.DocumentReadingOptionKey: Any] = [ .documentType: NSAttributedString.DocumentType.html ] var html2AttributedString: NSMutableAttributedString? { autoreleasepool { guard let htmlData = self.data(using: .utf16) else { return nil } do { return try NSMutableAttributedString( data: htmlData, options: Self.htmlParseOptions, documentAttributes: nil ) } catch { print("HTML解析失败: \(error)") return nil } } } }
方案二:用第三方库手动构建富文本
如果系统API的泄漏问题无法解决,可以用轻量HTML解析库SwiftSoup手动解析标签并构建AttributedString,完全控制内存分配:
import SwiftSoup extension String { var html2AttributedString: NSMutableAttributedString? { autoreleasepool { do { let doc = try SwiftSoup.parse(self) let resultString = NSMutableAttributedString() // 遍历HTML节点,根据标签设置对应样式 for element in doc.body()?.children() ?? [] { let text = try element.text() var attributes = [NSAttributedString.Key: Any]() switch element.tagName().lowercased() { case "h1": attributes[.font] = UIFont.boldSystemFont(ofSize: 24) case "h2": attributes[.font] = UIFont.boldSystemFont(ofSize: 20) case "b", "strong": attributes[.font] = UIFont.boldSystemFont(ofSize: UIFont.systemFontSize) default: break } resultString.append(NSAttributedString(string: text, attributes: attributes)) } return resultString } catch { print("HTML解析失败: \(error)") return nil } } } }
注:可根据需求扩展更多标签(如p、i等)的样式处理逻辑。
方案三:通过WKWebView间接处理复杂HTML
如果HTML包含复杂样式表或嵌套结构,可借助WKWebView加载后再提取富文本:
import WebKit extension String { func html2AttributedString(completion: @escaping (NSMutableAttributedString?) -> Void) { let webView = WKWebView(frame: .zero) webView.loadHTMLString(self, baseURL: nil) webView.evaluateJavaScript("document.body.innerHTML") { result, error in guard let htmlContent = result as? String, error == nil else { completion(nil) return } guard let data = htmlContent.data(using: .utf16) else { completion(nil) return } let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [ .documentType: NSAttributedString.DocumentType.html ] do { let attrString = try NSMutableAttributedString( data: data, options: options, documentAttributes: nil ) completion(attrString) } catch { completion(nil) } // 及时释放webView避免内存占用 webView.removeFromSuperview() } } }
使用示例:
"<H1>Hello world</H1><h2><b>, abc</b><h2>".html2AttributedString { attrText in DispatchQueue.main.async { self.lblHeader.attributedText = attrText } }
内容的提问来源于stack exchange,提问作者S K
相关产品推荐
相关产品推荐

