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

Xcode 14中SwiftUI如何读取JSON文件中的HTML格式文本?

问题描述

我有一个包含HTML样式标记(加粗<b>、斜体<i>等)的JSON文件,需要在SwiftUI的详情页中保留这些格式展示文本。目前已完成JSON数据读取并显示在列表中,点击可跳转至详情页,但始终无法实现保留HTML格式的文本展示。我使用Xcode 14和SwiftUI,搜索过资料及Apple开发者文档都没找到可行方案,应用必须正确显示这些格式,而这在HTML/JS里很容易实现,自己刚接触SwiftUI,不清楚哪里出错了。附上JSON结构和LandmarkDetail视图代码,尝试添加属性时均报错,寻求帮助。

JSON示例

[
    { 
        "imageurl": "1.png",
        "levelLongDesc":"A longer description",
        "id": "1.",
        "name": "A name",
        "page": "Details",
        "description":"<p><b>E pluribus unum</b></p><b>Instructions.</b> Latin for “Out of many one”, is a motto requested by <i>Pierre Eugene du Simitiere</i> (originally Pierre-Eugène Ducimetière) and found in 1776 on the Seal of the United States, along with Annuit cœptis and Novus ordo seclorum, and adopted by an Act of Congress in 1782.</p><p>",
        "videoDemo":"myvideo"
    }
]

现有代码示例

import SwiftUI

struct LandmarkDetail: View {
var landmark: Landmark
@State var Description = AttributedString("")
var body: some View {

    NavigationView{
    ScrollView {
        RectImage(image: landmark.image)
           
            .padding(.top, 30)
          
            .font(.subheadline)
            .foregroundColor(.secondary)
        
            Divider()
        
            Text("\(landmark.name)")
          
        
            Text(landmark.description)
            .font(.title3)
            .padding(.horizontal, 20)
            .onAppear {
                (addStyling(landmark.description))
            }
            } .padding()
        
        }.navigationTitle(landmark.name)
        .navigationBarTitleDisplayMode(.inline)
       
    }
private func addStyling(_ htmlString: String) -> NSAttributedString {
        var resultString = NSAttributedString()
        var data = Data()
        // Add the html data/ var in which you stored it
    data.append(Data(landmark.description.utf8))
        // Convert the attributed String
        do {
            let attributedString = try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil)
            resultString = attributedString
        } catch {
            print(error)
        }
        return resultString
    }
}

解决方案

你的核心问题是没有把转换后的富文本赋值给用于展示的变量,且没有正确适配SwiftUI的AttributedString类型。以下是修正后的代码:

import SwiftUI

struct LandmarkDetail: View {
    var landmark: Landmark
    // 存储转换后的富文本,符合Swift命名规范
    @State private var attributedDescription = AttributedString("")
    
    var body: some View {
        NavigationView {
            ScrollView {
                RectImage(image: landmark.image)
                    .padding(.top, 30)
                    .font(.subheadline)
                    .foregroundColor(.secondary)
                
                Divider()
                
                Text(landmark.name)
                
                // 直接使用转换后的富文本
                Text(attributedDescription)
                    .font(.title3)
                    .padding(.horizontal, 20)
            }
            .padding()
            .navigationTitle(landmark.name)
            .navigationBarTitleDisplayMode(.inline)
            // 视图出现时执行转换
            .onAppear {
                convertHtmlToAttributedString()
            }
        }
    }
    
    private func convertHtmlToAttributedString() {
        // 直接将HTML字符串转为Data,简化逻辑
        guard let data = landmark.description.data(using: .utf8) else { 
            attributedDescription = AttributedString(landmark.description)
            return 
        }
        
        do {
            let nsAttributedString = try NSAttributedString(
                data: data,
                options: [.documentType: NSAttributedString.DocumentType.html],
                documentAttributes: nil
            )
            // 将UIKit的NSAttributedString转为SwiftUI可用的AttributedString
            attributedDescription = AttributedString(nsAttributedString)
        } catch {
            print("HTML转换失败: \(error.localizedDescription)")
            // 转换失败时兜底显示原始文本
            attributedDescription = AttributedString(landmark.description)
        }
    }
}

关键修改说明

  1. 重命名@State变量为attributedDescription,符合Swift命名规范,专门用于存储转换后的富文本。
  2. 在onAppear中调用转换方法,确保视图加载时完成HTML到富文本的转换。
  3. 展示文本时使用Text(attributedDescription),直接渲染带格式的内容。
  4. 简化Data创建逻辑,直接通过htmlString.data(using: .utf8)获取数据。
  5. 添加错误兜底逻辑,转换失败时显示原始文本,避免空白。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:35:18