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

UITextView加载含有序列表的HTML显示异常问题排查与解决

问题根源分析

UITextView加载HTML有序列表时显示异常,核心原因在于:

  1. 系统自带的NSHTMLTextDocumentType解析器(基于旧版WebKit实现)对HTML列表元素的原生样式支持非常有限,默认渲染的缩进、编号对齐、间距等效果和你预期的原生列表样式差异很大,而且不同iOS版本还可能出现不一致的表现。
  2. 你无法修改的原HTML里大概率没有定义列表的CSS样式规则,解析器只能用默认的简陋样式来渲染,自然达不到预期。
解决方法(App端处理,无需修改原HTML)

最靠谱的方案是给原HTML注入自定义CSS样式,强制统一列表的渲染效果,再转换为富文本加载到UITextView中。下面是具体的Swift代码实现:

方法1:注入CSS修复列表样式

通过给原HTML包裹一个带<style>标签的HTML结构,自定义有序列表和列表项的样式:

func htmlToStyledAttributedString(_ rawHTML: String) -> NSAttributedString? {
    // 包裹原HTML,注入自定义CSS
    let wrappedHTML = """
    <html>
        <head>
            <style>
                /* 重置列表默认样式 */
                ol {
                    margin: 0 0 16px 24px;
                    padding: 0;
                    list-style-type: decimal; /* 确保是数字编号 */
                }
                li {
                    margin-bottom: 8px; /* 列表项之间的间距 */
                    padding-left: 6px;
                    line-height: 1.5; /* 行高优化 */
                }
            </style>
        </head>
        <body>
            \(rawHTML)
        </body>
    </html>
    """
    
    guard let htmlData = wrappedHTML.data(using: .utf8) else { return nil }
    
    let parseOptions: [NSAttributedString.DocumentReadingOptionKey: Any] = [
        .documentType: NSAttributedString.DocumentType.html,
        .characterEncoding: String.Encoding.utf8.rawValue
    ]
    
    do {
        return try NSAttributedString(data: htmlData, options: parseOptions, documentAttributes: nil)
    } catch {
        print("HTML转富文本失败: \(error.localizedDescription)")
        return nil
    }
}

// 使用示例
if let yourOriginalHTML = "这里替换成你的原HTML文本",
   let styledText = htmlToStyledAttributedString(yourOriginalHTML) {
    yourTextView.attributedText = styledText
    // 调整UITextView的内边距,让列表对齐更自然
    yourTextView.textContainer.lineFragmentPadding = 0
    yourTextView.textContainerInset = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12)
}

方法2:手动调整富文本的段落样式(进阶优化)

如果注入CSS后还是有编号和文本对齐的问题,可以遍历生成的富文本,手动修改段落样式:

func fixListParagraphAlignment(in attributedText: NSAttributedString) -> NSAttributedString {
    let mutableText = NSMutableAttributedString(attributedString: attributedText)
    let fullRange = NSRange(location: 0, length: mutableText.length)
    
    mutableText.enumerateAttribute(.paragraphStyle, in: fullRange) { value, range, _ in
        guard var paraStyle = value as? NSMutableParagraphStyle else { return }
        
        // 设置悬挂缩进,让编号和文本对齐
        paraStyle.headIndent = 28
        paraStyle.firstLineHeadIndent = 0
        paraStyle.lineSpacing = 4
        paraStyle.paragraphSpacing = 4
        
        mutableText.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    }
    
    return mutableText
}

// 用法:在转换富文本后调用
let baseAttributedText = htmlToStyledAttributedString(yourOriginalHTML)
let finalAttributedText = fixListParagraphAlignment(in: baseAttributedText!)
yourTextView.attributedText = finalAttributedText

额外提示(iOS 15+)

如果你只需要支持iOS 15及以上版本,可以用新的AttributedString结构体来解析HTML,它对列表的支持更完善,代码也更简洁:

if let yourOriginalHTML = "你的原HTML文本",
   let htmlData = yourOriginalHTML.data(using: .utf8) {
    do {
        var attributedString = try AttributedString(
            data: htmlData,
            options: .init(documentType: .html),
            baseURL: nil
        )
        // 可以直接修改富文本的样式属性
        attributedString.font = UIFont.systemFont(ofSize: 16)
        yourTextView.attributedText = NSAttributedString(attributedString)
    } catch {
        print("解析失败: \(error)")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:12:06