【问题标题】:Swift - Update List from different ViewSwift - 从不同的视图更新列表
【发布时间】:2020-12-31 14:51:34
【问题描述】:

我的 Swift 项目中有 2 个视图,当我单击第二个视图上的按钮时,我想更新第一个视图中的列表。我不知道该怎么做!如果我在 MainView 中使用静态变量,然后从 secondView 编辑此变量,它可以工作,但不会更新。如果我不使用静态,而是使用@State,它会更新,但我无法从我的 secondView 访问它。

下面是代码:

import SwiftUI

struct ContentView: View {
    
    var body: some View {

        TabView {
         
            MainView()
                .tabItem() {
                    VStack {
                        Image(systemName: "circle.fill")
                        Text("MainView")
                    }
                }.tag(0)
            
            UpdateOtherViewFromHere()
                .tabItem() {
                    VStack {
                        Image(systemName: "circle.fill")
                        Text("SecondView")
                    }
                }.tag(1)
        }
    
    
    }
}


struct MainView: View {
    
    var arrayList: [CreateListItems] = []
    
    init() {
        let a = CreateListItems(name: "First Name!")
        let b = CreateListItems(name: "Second Name!")
        let c = CreateListItems(name: "Third Name!")

        arrayList.append(a)
        arrayList.append(b)
        arrayList.append(c)
        
    }
    
    var body: some View {
        return VStack {
            ZStack {
            NavigationView {
                
                List {
                    ForEach(arrayList) { x in
                        Text("\(x.name)")
                    }
                }.navigationBarTitle("Main View")
   
            }

        }
        }
    }
}

struct UpdateOtherViewFromHere: View {
    
    func updateList() {
        //Code that should remove "FirstName" from the List in MainView
    }
    
    var body: some View {
        return VStack {
            Button(action: {
                updateList()
            }) {
                Image(systemName: "heart.slash")
                    .font(.largeTitle)
                    

                Text("Click Me!")
            }
        }
    }
}


struct CreateListItems: Identifiable {
    var id: UUID = UUID()
    var name: String
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

【问题讨论】:

  • 你应该将你的 arrayList 移动到一个单独的类中

标签: ios swift list view


【解决方案1】:

您可以使用@State@Binding 分享它

struct ContentView: View {
     @State var arrayList: [CreateListItems] = []

struct MainView: View {
     @Binding var arrayList: [CreateListItems]

struct UpdateOtherViewFromHere: View {
     @Binding var arrayList: [CreateListItems]

或者您使用 MVVM 模式并将列表存储在 ObservableObject 中并使用 @StateObject/@ObservedObject(源)并使用 @EnvironmentObject(连接)在您的视图之间共享它。

https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app

class ParentViewModel: ObservableObject{
    @Published var arrayList: [CreateListItems] = []
    
    init(){
        addSamples()
    }
    func addSamples()  {
        let a = CreateListItems(name: "First Name!")
        let b = CreateListItems(name: "Second Name!")
        let c = CreateListItems(name: "Third Name!")
        
        arrayList.append(a)
        arrayList.append(b)
        arrayList.append(c)
    }
    func updateList() {
        let a = CreateListItems(name: "\(arrayList.count + 1) Name!")
        arrayList.append(a)
    }
}
struct ParentView: View {
    @StateObject var vm: ParentViewModel = ParentViewModel()
    var body: some View {
        
        TabView {
            MainView().environmentObject(vm)
                .tabItem() {
                    VStack {
                        Image(systemName: "circle.fill")
                        Text("MainView")
                    }
                }.tag(0)
            
            UpdateOtherViewFromHere().environmentObject(vm)
                .tabItem() {
                    VStack {
                        Image(systemName: "circle.fill")
                        Text("SecondView")
                    }
                }.tag(1)
        }
    }
}
struct MainView: View {
    @EnvironmentObject var vm: ParentViewModel
    
    var body: some View {
        return VStack {
            ZStack {
                NavigationView {
                    
                    List {
                        ForEach(vm.arrayList) { x in
                            Text(x.name)
                        }
                    }.navigationBarTitle("Main View")
                }
            }
        }
    }
}
    
struct UpdateOtherViewFromHere: View {
    @EnvironmentObject var vm: ParentViewModel
    var body: some View {
        return VStack {
            Button(action: {
                vm.updateList()
            }) {
                Image(systemName: "heart.slash")
                    .font(.largeTitle)

                Text("Click Me!")
            }
        }
    }
}

【讨论】:

  • 为什么在“ContentView”中使用@State?这只是为了测试还是有合理的理由?
  • 因为@State 是事实的来源。它需要在 ParentView 中,以便孩子们可以共享它。它不必在ContentView 中,它只需要在ParentView 中,因此可以与孩子建立双向连接(@Binding)。
  • 但需要注意的是,从 View updateList() 操作列表是一种不好的做法,并且您的 MainView init() 中的代码应该与 ObservableObject 一起位于数组本身。这使得代码可重用和解耦。
  • 我添加了一些代码来说明基础知识。你应该看看 Apple SwiftUI 教程developer.apple.com/tutorials/swiftui
猜你喜欢
  • 1970-01-01
  • 2017-05-21
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多