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
相关产品推荐
相关产品推荐

