SwiftUI:监听我的数据中的变化,让其他视图使用更新的数据

Posted

技术标签:

【中文标题】SwiftUI:监听我的数据中的变化,让其他视图使用更新的数据【英文标题】:SwiftUI: Listening for changes in my data to have other views use the updated data 【发布时间】:2021-06-11 04:40:38 【问题描述】:

我的主要视图是解码 JSON,然后枚举该 JSON 以显示城镇列表,您可以在其中切换 favorite 字段。 我想有一个单独的视图来只显示favorited 的城镇,我怀疑我想使用 ObservableObject 和@Published 来监听countries 的变化。我只是不知道如何实现这一点,因为我没有使用任何 class 对象。

Towns.json

[
    
      "display_name": "California",
      "favorite": false,
    ,
    
      "display_name": "Colorado",
      "favorite": false,
    

]

Town.swift

struct Town: Codable, Identifiable 
    var id: String image
    let display_name: String
    var favorite: Bool

MainView.swift

struct ContentView : View 

    @State var towns : [Town] = Bundle.main.decode("Towns.json")

    var body: some View 
        ForEach(Array(towns.enumerated()), id: \.1.id)  (index,town) in
            LazyVStack(spacing: 20) 
                HStack 
                    Text(town.display_name)
                    Spacer()
                    Button 
                        towns[index].favorite.toggle()
                     label: 
                        if town.favorite 
                            Image(systemName: "flame").foregroundColor(.red)
                         else 
                            Image(systemName: "flame.fill").foregroundColor(.red)
                        
                    
                
            
        
    

【问题讨论】:

【参考方案1】:

是的,您可以使用 ObservableObject,但如果您只想在另一个视图中显示“最喜欢”的城镇,我会这样做:

struct Town: Codable, Identifiable 
    var id: String = UUID().uuidString // for testing
    let display_name: String
    var favorite: Bool


struct ContentView: View 
    @State var showSecondView = false
    // @State var towns: [Town] = Bundle.main.decode("Towns.json")
    // for testing
    @State var towns: [Town] = [Town(display_name: "California", favorite: false),
                               Town(display_name: "Colorado", favorite: false)]

    var body: some View 
        VStack 
            
            Button ("Show SecondView")  showSecondView.toggle() 
            
            ForEach(Array(towns.enumerated()), id: \.1.id)  (index,town) in
                LazyVStack(spacing: 20) 
                    HStack 
                        Text(town.display_name)
                        Spacer()
                        Button 
                            towns[index].favorite.toggle()
                         label: 
                            if town.favorite 
                                Image(systemName: "flame").foregroundColor(.red)
                             else 
                                Image(systemName: "flame.fill").foregroundColor(.red)
                            
                        
                    
                
            
        .sheet(isPresented: $showSecondView) 
            SecondTownView(towns: $towns)
        
    


struct SecondTownView: View 
    @Binding var towns: [Town]
    var body: some View 
        // here filter the towns on favorite
        ForEach(Array(towns.filter$0.favorite.enumerated()), id: \.1.id)  (index,town) in
            LazyVStack(spacing: 20) 
                HStack 
                    Spacer()
                    Text(town.display_name)
                    Spacer()
                
            
        
    

【讨论】:

以上是关于SwiftUI:监听我的数据中的变化,让其他视图使用更新的数据的主要内容,如果未能解决你的问题,请参考以下文章

观察 SwiftUI 中的帧变化

Swiftui @EnvironmentObject 在视图中更新

SwiftUI:如何使列表视图透明?如何更改列表视图背景颜色?

SwiftUI 在视图之间共享模型数据

如何最好地传递数据以在 swiftui 中进行表单编辑(同时让该数据可用于父视图和其他子视图)?

观察自定义视图 SwiftUI 中的属性变化