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

Swift开发中如何向数据模型所属的类传递JSON文件名

实现方案

第一步:抽离通用可复用的数据模型与数据加载类

首先移除和特定文件名绑定的前缀标识,把数据加载类修改为支持接收文件名参数初始化:

// 通用时间序列数据模型,两个格式一致的JSON均可复用该结构
struct TimeSeriesData: Codable {
    var timeSeriesDaily: [(Date, Double)]
    // 原VFIAXTimeSeriesData包含的其他属性可直接迁移至此
}

// 通用数据加载类,支持传入自定义文件名
class TimeSeriesDataLoader {
    var timeSeriesData = TimeSeriesData(timeSeriesDaily: [])
    // 初始化时传入不带.json后缀的文件名即可
    init(fileName: String) {
        getData(fileName: fileName)
    }
    
    private func getData(fileName: String) {
        guard let url = Bundle.main.url(forResource: fileName, withExtension: "json")
        else {
            print("Json文件不存在: \(fileName)")
            return
        }
        let decoder = JSONDecoder()
        do {
            let data = try Data(contentsOf: url)
            self.timeSeriesData = try decoder.decode(TimeSeriesData.self, from: data)
            self.timeSeriesData.timeSeriesDaily = self.timeSeriesData.timeSeriesDaily.sorted() { $0 < $1 }
            let lastYear: Date = Calendar.current.date(byAdding: .year , value: -1, to: timeSeriesData.timeSeriesDaily[timeSeriesData.timeSeriesDaily.count - 1].0) ?? Date()
            var index = 0
            for i in 0...(timeSeriesData.timeSeriesDaily.count - 1) {
                if timeSeriesData.timeSeriesDaily[i].0 >= lastYear {
                    index = i
                    break
                }
            }
            timeSeriesData.timeSeriesDaily.removeSubrange(0..<index)
        } catch {
            print("\(fileName)文件解析错误: \(error)")
        }
    }
}

第二步:简化通用DataModel

无需再保留针对单个文件的专用DataModel,直接复用通用结构:

struct CommonTimeSeriesDataModel {
    var dataLoader: TimeSeriesDataLoader
    init(fileName: String) {
        self.dataLoader = TimeSeriesDataLoader(fileName: fileName)
    }
}

第三步:调整ViewModel(两种可选方案)

方案A:两个业务逻辑无差异,直接用通用ViewModel

class CommonTimeSeriesViewModel: ObservableObject {
    @Published private var dataModel: CommonTimeSeriesDataModel
    var timeSeriesDaily : [(Date, Double)] {
        return dataModel.dataLoader.timeSeriesData.timeSeriesDaily
    }
    init(fileName: String) {
        self.dataModel = CommonTimeSeriesDataModel(fileName: fileName)
    }
}

使用时不同视图传入对应文件名即可:

  • VFIAX对应视图:@StateObject var vm = CommonTimeSeriesViewModel(fileName: "VFIAXData10")
  • 另一个同格式JSON对应视图:@StateObject var vm = CommonTimeSeriesViewModel(fileName: "你的另一个文件名")

方案B:两个ViewModel有专属业务逻辑,保留独立ViewModel

仅修改初始化参数即可,无需重复写DataModel和加载逻辑:

class VFIAXDataViewModel: ObservableObject {
    @Published private var vfiaxDataModel: CommonTimeSeriesDataModel = CommonTimeSeriesDataModel(fileName: "VFIAXData10")
    var timeSeriesDaily : [(Date, Double)] {
        return vfiaxDataModel.dataLoader.timeSeriesData.timeSeriesDaily
    }
    // 此处可添加VFIAX专属的业务逻辑
}

可选优化

  • 可直接将数据加载逻辑迁移至ViewModel层,省略中间的DataModel层,进一步精简代码
  • 若剩余第三个JSON格式差异不大,可通过枚举关联不同模型类型,进一步复用加载逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:39:04