你应该使用@EnvironmentObject
。它允许共享对象,这对于与其他视图共享数据非常重要。
我正在使用一个Shopping
本例中的对象。这个应用程序就像一个购物清单。整个项目可以在 GitHub 上找到here https://github.com/George-J-E/ShoppingListSwiftUIExample.
我真的希望这有用,因为它花了很长时间。这只是一个general如何使用的示例@EnvironmentObject
有效地之间View
s.
该应用程序如下所示:
创建项目
(can be downloaded through GitHub, see above link)
1:首先,在你的SceneDelegate.swift
, 代替:
let contentView = ContentView()
with:
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
让可选的@State
的工作(信用here https://stackoverflow.com/a/57041232/9607863,尽管这已被简化):
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
}
}