首页 > 解决方案 > 如何快速更改从本地 json 文件加载的数据并在不同页面中同时显示更改的数据

问题描述

我试图将本地 JSON 文件解析为我自己的结构,它运行良好。现在我想更改DOUBAN_VOTES数组中的一些值。我不知道如何做到这一点以及如何在不同的页面上同时显示这些更改的数据。

问题是当我尝试将新值传递给我的电影数据时,我没有改变它。例如:DOUBAN_VOTES是 3000,我将它添加到 3001 处mypage.swift,但在另一个页面上,它仍然显示为 3000

我的结构

import Foundation


struct Movie:Codable {
    var MOVIE_ID:String
    var NAME:String
    var ALIAS:String?
    var ACTORS:String?
    var COVER:String?
    var DIRECTORS:String?
    var DOUBAN_SCORE:String?
    var DOUBAN_VOTES:String?
    var GENRES:String?
    var IMDB_ID:String?
    var LANGUAGES:String?
    var MINS:String?
    var OFFICIAL_SITE:String?
    var REGIONS:String?
    var RELEASE_DATE:String?
    var SLUG:String?
    var STORYLINE:String?
    var TAGS:String?
    var YEAR:String?
    var ACTOR_IDS:String?
    var DIRECTOR_IDS:String?
    var isFavered:Bool = false
    enum CodingKeys: String, CodingKey {
        case MOVIE_ID, NAME,ALIAS,ACTORS,COVER,DIRECTORS,DOUBAN_SCORE
        case DOUBAN_VOTES,GENRES,IMDB_ID,LANGUAGES,MINS,OFFICIAL_SITE
        case REGIONS,RELEASE_DATE,SLUG,STORYLINE,TAGS,YEAR,ACTOR_IDS,DIRECTOR_IDS
    }
    
}
class moviedata: ObservableObject {
    @Published var myMovieData:[Movie] = Bundle.main.decode(filename:"movieData1.json")
}

extension Bundle{
    func decode<T:Codable>(filename:String) -> T {
        guard let url = Bundle.main.url(forResource: filename, withExtension: nil),
              let data = try? Data(contentsOf: url),
              let getResponse = try? JSONDecoder().decode(T.self, from: data)
              else { fatalError("no data")}
        return getResponse
    }
}

我的 SwiftUI 文件:我想在单击“确认”按钮时将值传递给数组


import SwiftUI

struct myPage: View {
    //@State var movieData: [Movie] = []
    @ObservedObject var movieData=moviedata()
    @State private var index = 0
    @State private var nf = NumberFormatter()
    @State private var temp:Int=0;
    var body: some View {
        VStack {
            //Text(movieData.myMovieData[index].NAME)
            Text("vote: \(temp)")
            
            //Text(verbatim: vote)
            Button("next"){
                index=index+1
            }
            Button("add"){
                temp = temp + 1
                
            }
            Button("comfirm"){
                movieData.myMovieData[index].DOUBAN_VOTES=String(temp)
            }
//here I want to change the data
            
        }.onChange(of: index, perform: { value in
           
                temp=nf.number(from: movieData.myMovieData[index].DOUBAN_VOTES ?? "0") as! Int
           
        })
        .onAppear{
            temp=nf.number(from: movieData.myMovieData[index].DOUBAN_VOTES ?? "0") as! Int
        }

    }
}

struct myPage_Previews: PreviewProvider {
    static var previews: some View {
        myPage()
    }
}

我的 json 文件

[
{
"MOVIE_ID":"27021694",
"NAME":"耶尔玛&quot;,
"ALIAS":"",
"ACTORS":"比莉·派佩/布伦丹·考威尔/约翰·麦克米兰",
"COVER":"",
"DIRECTORS":"西蒙·斯通&quot;,
"DOUBAN_SCORE":"8.2",
"DOUBAN_VOTES":"187",
"GENRES":"剧情/戏曲",
"IMDB_ID":"tt6847880",
"LANGUAGES":"英语",
"MINS":"0",
"OFFICIAL_SITE":"http://ntlive.nationaltheatre.org.uk/productions/ntlout22-yerma",
"REGIONS":"英国",
"RELEASE_DATE":"2017/8/31",
"SLUG":"72FZ3FZ3b",
"STORYLINE":"A young woman is driven to the unthinkable by her desperate desire to have a child in Simon Stone’s radical production of Lorca’s achingly powerful masterpiece.",
"TAGS":"NTLive/女性/舞台剧/戏剧/英国/英国国家剧院现场/BilliePiper/NTL",
"YEAR":"2017",
"ACTOR_IDS":"比莉·派佩:1049548|Maureen Beattie:|布伦丹·考威尔:1022987|约翰·麦克米兰:1319678|Charlotte Randle:|Thalissa Teixeira:",
"DIRECTOR_IDS":"西蒙·斯通:1336274"
}
]

标签: iosarraysjsonswiftxcode

解决方案


您可以在“ViewModel”(又名moviedata)中提供“确认”功能:

func confirm(movieID: String, votes: Int)

更好的是,在视图模型中管理投票数,而不是在视图中:

func upVote(movieID: String)
func downVote(movieID: String)

这些函数改变视图模型的内部状态,进而改变发布的变量myMovieData

这种变化将立即反映在观察它的视图中。

在您的按钮操作中,只需调用此确认函数:

    ...
    Button("comfirm") {
        let movie = movieData.myMovieData[index]
        movieData.confirm(movieID: movie.MOVIE_ID, votes: temp)
    }

最后的笔记

请修正拼写错误并为类、结构和变量名称应用通用的 Swift 样式。


推荐阅读