Swift - 从不同的视图更新列表

Posted

技术标签:

【中文标题】Swift - 从不同的视图更新列表【英文标题】:Swift - Update List from different View 【发布时间】: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 移动到一个单独的类中 【参考方案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

以上是关于Swift - 从不同的视图更新列表的主要内容,如果未能解决你的问题,请参考以下文章

从列表中选择并重新加载 Tableview Swift

Swift 在可滚动列表中添加项目

如何使用从图库中选择的新图像更新列表视图 [重复]

从 SwiftUI 中的工作表更新列表视图中的行

立即从进程回调输出更新列表视图 C# WPF

从广播接收器更新片段中的列表视图