[英]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传递到EditView , EditView 上的所有文本字段都是空的,值不会被传递。 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:该应用程序如下所示:
(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.