简体   繁体   English

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

[英]SwiftUI - pass data to different views

I am working on an App which has 4 different views.我正在开发一个有 4 个不同视图的应用程序。 The main view ( ContentView ), an AddView , an EditView , and a separated DataView with a class where I pass all the data by an ObservableObject to the other views.主视图( ContentView )、一个AddView 、一个EditView和一个分离的DataView ,其中包含一个类,我通过ObservableObject将所有数据传递给其他视图。

In the main view I have a list of items.在主视图中,我有一个项目列表。 In the AddView I add items to that list and from the ContentView .AddView 中,我将项目添加到该列表和ContentView I would like to be able to edit the added items by using a navigation link.我希望能够使用导航链接编辑添加的项目。 So from the main view I would like to go to EditView , change the values and go back to the ContentView again where I see the changed values.所以从主视图我想转到EditView ,更改值并再次返回ContentView ,在那里我看到更改的值。

Would you use ObservableObject for doing that or do I need EnvironmentObject?你会使用ObservableObject来做这件事还是我需要 EnvironmentObject? Because at the moment EditView is not working, I can't pass the data from ContentView to EditView , all the textfields on the EditView are empty, the values do not get passed over.因为此刻EditView不工作,我无法将数据从ContentView传递到EditViewEditView 上的所有文本字段都是空的,值不会被传递。 It works to pass the data from AddView to ContentView but then not from ContentView to EditView .它可以将数据从AddView 传递ContentView而不是从ContentView传递到EditView

Can someone tell me how the data has to be linked to all the views?有人能告诉我如何将数据链接到所有视图吗?

You should use @EnvironmentObject .您应该使用@EnvironmentObject It allows an object to be shared, which is very important for sharing data to other views.它允许共享一个对象,这对于将数据共享给其他视图非常重要。

I am using a Shopping object in this example.我在这个例子中使用了一个Shopping对象。 This app will act like a shopping list.这个应用程序就像一个购物清单。 This whole project is available of GitHub here .这整个项目可GitHub上的位置

I really hope this is useful, as it took quite a while.我真的希望这很有用,因为它花了很长时间。 This is just a general example of how to use @EnvironmentObject effectively between View s.这只是如何在View之间有效使用@EnvironmentObject一般示例。

The app looks like this:该应用程序如下所示:

应用程序的外观


Creating the project创建项目

(can be downloaded through GitHub, see above link) (可以通过GitHub下载,见上面的链接)

1: First, in your SceneDelegate.swift , replace: 1:首先,在你的SceneDelegate.swift ,替换:

let contentView = ContentView()

with:和:

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

2: Xcode will be complaining for now about Shopping not being made yet, so we will fix that next: 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: Next, we want the main content, ContentView : 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: Along with this extension to let optional @State s work (credit here , although this has been simplified): 4:随着这个extension ,让可选的@State工作(信用在这里,虽然这已经被简化):

extension Optional where Wrapped == String {

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

5: And then finally - the EditView , to allow you to edit the name of the item in the shopping list: 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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM