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

如何不新增id使模型遵循Identifiable协议?预览无内容排查

解决方案:不添加额外id让模型遵循Identifiable协议并修复预览无内容问题

一、核心问题分析

  • 当前模型手动添加了id字段,但JSON中无对应数据,导致解码失败,这是预览无内容的根本原因。
  • 遵循Identifiable协议仅需提供一个唯一的id属性,无需新增字段,可复用JSON中已有的service_id。
  • 模型中startDate、endDate定义为String,但JSON中是整数类型,类型不匹配也会导致解码失败。

二、修正模型代码

方式1:直接将service_id映射为id(推荐)

利用JSONDecoder的convertFromSnakeCase策略,把JSON的service_id直接映射到模型的id属性,无需额外计算属性:

struct ResorModel: Decodable, Identifiable { // Swift类型名采用大驼峰命名规范
    let id: Int // 对应JSON的service_id
    let monday: Int
    let tuesday: Int
    let wednesday: Int
    let thursday: Int
    let friday: Int
    let saturday: Int
    let sunday: Int
    let startDate: Int // 对应JSON的start_date,类型改为Int
    let endDate: Int // 对应JSON的end_date,类型改为Int
}

方式2:保留serviceId,添加计算属性id

如果需要保留serviceId字段,可通过计算属性返回它作为Identifiable的id:

struct ResorModel: Decodable, Identifiable {
    let serviceId: Int
    let monday: Int
    let tuesday: Int
    let wednesday: Int
    let thursday: Int
    let friday: Int
    let saturday: Int
    let sunday: Int
    let startDate: Int
    let endDate: Int
    
    // 计算属性,复用serviceId作为Identifiable的id
    var id: Int { serviceId }
}

三、修正控制器代码(规范命名+增强容错)

import Foundation

class ResorManager { // 类名改为更清晰的ResorManager
    var differentStops: [ResorModel] = [] // 修正拼写错误diffentStops -> differentStops
    
    init() {
        decodeResorData()
    }
    
    func decodeResorData() {
        guard let url = Bundle.main.url(forResource: "csvjson", withExtension: "json") else {
            print("JSON文件未找到")
            return
        }
        do {
            let data = try Data(contentsOf: url)
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            differentStops = try decoder.decode([ResorModel].self, from: data)
        } catch {
            print("JSON解码错误: \(error)")
        }
    }
}

四、修正视图代码(适配模型变更)

如果startDate是Int类型,展示时需要转为String:

import SwiftUI

struct ShowStopsView: View { // 视图名采用大驼峰命名
    let resorManager = ResorManager()
    
    var body: some View {
        List(resorManager.differentStops) { resa in
            Text("\(resa.startDate)") // 将Int转为String展示
        }
    }
}

#Preview {
    ShowStopsView()
}

五、验证效果

运行预览后,应该能正常加载并展示所有startDate数据。如果仍无内容,检查:

  • JSON文件是否正确添加到项目中(确保勾选了对应的target)
  • 控制台是否有错误输出,根据错误信息进一步排查

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:10:55