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

Swift如何修改本地JSON加载的Movie数据并实现多页面同步更新展示

问题根本原因

  • 你在每个用到moviedata的页面都单独执行了@ObservedObject var movieData=moviedata(),相当于每个页面都持有一个独立的moviedata实例,所有实例都会从Bundle加载原始JSON数据,你在A页面修改的是A实例的内存数据,B页面读取的是B实例的原始数据,自然不会同步。
  • 你当前的修改仅存在于内存中,Bundle内的原始JSON是只读不可修改的,App重启后所有修改都会重置。

修复方案

1. 全局唯一数据源配置

给moviedata类添加单例配置,禁止外部随意创建新实例,保证全App读写同一份数据:

class moviedata: ObservableObject {
    // 全局唯一共享实例
    static let shared = moviedata()
    @Published var myMovieData:[Movie] = []
    // 私有初始化方法,防止外部新建实例
    private init() {
        myMovieData = Bundle.main.decode(filename:"movieData1.json")
    }
}

在App主入口将共享实例注入到视图树中,所有子页面都可以直接读取:

// 你的App入口文件,比如XXApp.swift
@main
struct MovieApp: App {
    // 持有全局数据实例用@StateObject,避免实例被意外销毁
    @StateObject private var movieData = moviedata.shared
    var body: some Scene {
        WindowGroup {
            // 替换成你的根视图
            ContentView()
                .environmentObject(movieData)
        }
    }
}

2. 所有页面统一读取全局数据

把myPage里单独初始化moviedata的代码替换为读取环境对象,其他用到电影数据的页面也做相同修改:

// 删掉原来的@ObservedObject var movieData=moviedata(),换成下面这行
@EnvironmentObject var movieData: moviedata

修改完成后所有页面读写的都是同一份数据,修改后会自动同步到所有引用页面。

3. 可选:实现修改持久化

如果需要App重启后仍保留修改内容,需要把修改后的数据写入沙盒目录,下次启动优先读取沙盒数据,没有再加载Bundle原始文件。
给moviedata添加读写沙盒的扩展方法:

extension moviedata {
    // 加载数据:优先读沙盒,没有再读Bundle原始数据
    func loadData() {
        let sandboxPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("movieData1.json")
        guard let data = try? Data(contentsOf: sandboxPath),
              let decodedData = try? JSONDecoder().decode([Movie].self, from: data) else {
            // 沙盒无数据,加载Bundle原始文件
            myMovieData = Bundle.main.decode(filename:"movieData1.json")
            return
        }
        myMovieData = decodedData
    }
    
    // 将修改后的数据保存到沙盒
    func saveToSandbox() {
        let sandboxPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("movieData1.json")
        do {
            let encodedData = try JSONEncoder().encode(myMovieData)
            try encodedData.write(to: sandboxPath)
        } catch {
            print("数据保存失败: \(error.localizedDescription)")
        }
    }
}

修改moviedata的初始化方法调用loadData:

private init() {
    loadData()
}

每次修改数据后调用保存方法即可持久化:

Button("comfirm"){
    movieData.myMovieData[index].DOUBAN_VOTES=String(temp)
    movieData.saveToSandbox()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 05:00:04