Deberías usar @EnvironmentObject
. Permite compartir un objeto, lo cual es muy importante para compartir datos con otras vistas.
Estoy usando un Shopping
objeto en este ejemplo. Esta aplicación actuará como una lista de compras. Todo este proyecto está disponible en GitHub aquí .
Realmente espero que esto sea útil, ya que tomó bastante tiempo. Este es solo un ejemplo general de cómo usar de manera @EnvironmentObject
efectiva entre View
s.
La aplicación se ve así:

Creando el proyecto
(se puede descargar a través de GitHub, ver enlace anterior)
1: Primero, en su SceneDelegate.swift
, reemplace:
let contentView = ContentView()
con:
let contentView = ContentView().environmentObject(Shopping())
2: Xcode se quejará por ahora de Shopping
que aún no está hecho, así que lo arreglaremos a continuación:
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: A continuación, queremos que el contenido principal, 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: Junto con esto extension
para permitir que @State
funcionen los opcionales (crédito aquí , aunque esto se ha simplificado):
extension Optional where Wrapped == String {
var bound: String {
get {
return self ?? ""
}
set {
self = newValue
}
}
}
5: Y finalmente, el EditView
, para permitirle editar el nombre del artículo en la lista de compras:
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
}
}