SwiftUI - 将数据传递到不同的视图

Posted

技术标签:

【中文标题】SwiftUI - 将数据传递到不同的视图【英文标题】:SwiftUI - pass data to different views 【发布时间】:2020-01-16 13:05:16 【问题描述】:

我正在开发一个有 4 种不同视图的应用程序。主视图 (ContentView)、一个 AddView、一个 EditView 和一个单独的 DataView,其中包含我通过 ObservableObject 将所有数据传递给其他视图。

在主视图中,我有一个项目列表。在 AddView 中,我将项目添加到该列表和 ContentView。我希望能够使用导航链接编辑添加的项目。因此,我想从主视图转到 EditView,更改值,然后再次返回 ContentView,我会看到更改后的值。

您会使用 ObservableObject 来执行此操作,还是我需要 EnvironmentObject?因为目前 EditView 不起作用,我无法将数据从 ContentView 传递到 EditView 上的所有文本字段EditView 为空,值不会被传递。它可以将数据从 AddView 传递到 ContentView,但不能从 ContentView 传递到 EditView

谁能告诉我如何将数据链接到所有视图?

【问题讨论】:

使用@EnvironmentObject。它允许所有添加了这个的视图共享包含共享数据的同一对象。如果您希望我发布示例答案,请告诉我。 如果您可以为我的项目发布一个带有主视图、添加视图和编辑视图的示例,那就太好了。提前致谢! 【参考方案1】:

您应该使用@EnvironmentObject。它允许共享对象,这对于将数据共享给其他视图非常重要。

我在这个例子中使用了Shopping 对象。这个应用程序将像一个购物清单。整个项目在 GitHub here 上可用。

我真的希望这很有用,因为它花了很长时间。这只是一个一般示例,说明如何在Views 之间有效地使用@EnvironmentObject

应用如下所示:


创建项目

(可以通过GitHub下载,见上链接)

1:首先,在您的SceneDelegate.swift 中,替换:

let contentView = ContentView()

与:

let contentView = ContentView().environmentObject(Shopping())

2: Xcode 现在会抱怨 Shopping 还没有生成,所以我们接下来会解决这个问题:

class Shopping: ObservableObject 
    
    @Published var list = [
        ShoppingItem("Bread", quantity: 1),
        ShoppingItem("Milk", quantity: 2),
        ShoppingItem("Eggs", quantity: 12)
    ]
    
    func addItem(_ item: ShoppingItem) 
        list.append(item)
    



class ShoppingItem: Identifiable 
    
    var name: String
    var quantity: Int
    
    init(_ name: String, quantity: Int) 
        self.name = name
        self.quantity = quantity
    

3:接下来,我们要主要内容,ContentView

struct ContentView: View 

    @EnvironmentObject private var shopping: Shopping
    @State private var newItem: String?
    
    var body: some View 
        NavigationView 
            List 
                ForEach(shopping.list)  item in
                    NavigationLink.init(destination: EditView(currentItem: item)) 
                        HStack 
                            Text(item.name)
                            Spacer()
                            Text(String(item.quantity))
                            Spacer().frame(width: 10)
                        
                    
                
                
                if newItem != nil 
                    TextField("New Item", text: $newItem.bound, onCommit: 
                        if !self.newItem!.isEmpty 
                            self.shopping.addItem(ShoppingItem(self.newItem!, quantity: 1))
                        
                        self.newItem = nil
                    )
                
            
            .navigationBarTitle("Shopping List")
            .navigationBarItems(trailing: Button(action: 
                self.newItem = ""
            , label: 
                Image(systemName: "plus.circle.fill")
                    .resizable()
                    .frame(width: 25, height: 25)
            ))
        
    

4:连同这个extension,让可选的@States 工作(信用here,虽然这已经被简化了):

extension Optional where Wrapped == String 

    var bound: String 
        get 
            return self ?? ""
        
        set 
            self = newValue
        
    

5:最后 - EditView,允许您编辑购物清单中的商品名称:

struct EditView: View 

    let currentItem: ShoppingItem
    @EnvironmentObject private var shopping: Shopping
    @State private var name = ""
    
    var body: some View 
        TextField("Item", text: $name, onCommit: saveName)
            .padding()
            .background(Color.gray)
            .onAppear(perform: setName)
    
    
    private func saveName() 
        shopping.objectWillChange.send()
        currentItem.name = name
    
    private func setName() 
        name = currentItem.name
    

【讨论】:

非常感谢!这将帮助我完成我的应用程序:) @Distace 很高兴它有帮助! ? 我要感谢您付出额外的努力并为您的同行创建了一个特殊的项目。向您致敬,先生!

以上是关于SwiftUI - 将数据传递到不同的视图的主要内容,如果未能解决你的问题,请参考以下文章

将数据从简单的 NSView 传递到 SwiftUI 视图

如何将数据从子视图传递到父视图到 SwiftUI 中的另一个子视图?

将数据从模型传递到 SwiftUI 中的视图

将数据从 UIViewRepresentable 函数传递到 SwiftUI 视图

将数据从 SwiftUI 传递到 UIKit 的回调

如何将数据从父模型类传递到 SwiftUI 中的子视图