@EnvironmentObject属性在swiftUI中不能正常工作



从ViewModel更新cartArray并不追加到当前的元素,而是每次都添加新的对象。我需要维护cartArray作为全局数组,以便它可以从项目的任何视图访问。我从ViewModel向cartArray添加元素。我采用了一个单独的类DataStorage,它具有可以在整个项目中访问的对象

Example_AppApp.swift
import SwiftUI
@main
struct Example_AppApp: App {
var body: some Scene {
WindowGroup {
ContentView().environmentObject(DataStorage())
}
}
}
DataStorage.swift
import Foundation
class DataStorage: ObservableObject {
@Published var cartArray = [Book]()
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var showSheetView = false
var body: some View {
NavigationView{

ListViewDisplay()
.navigationBarItems(trailing:
Button(action: {
self.showSheetView.toggle()
}) {
Image(systemName: "cart.circle.fill")
.font(Font.system(.title))
}
)



}.sheet(isPresented: $showSheetView) {
View3()
}

}
}

struct ListViewDisplay: View{


var book = [
Book(bookId: 1 ,bookName: "Catch-22"),
Book(bookId: 2 ,bookName: "Just-Shocking" ),
Book(bookId: 3 ,bookName: "Stephen King" ),
Book(bookId: 4,bookName: "A Gentleman in Moscow"),
]

var body: some View {
List(book, id: .id) { book in
Text(book.bookName)
NavigationLink(destination: View1(book: book)) {

}
}

}
}

View1Modal.swift
import Foundation
struct Book: Codable, Identifiable {
var id:String{bookName}  
var bookId : Int
var bookName: String
}
struct BookOption: Codable{
var name: String
var price: Int
}
View1ViewModel.swift
import Foundation
import Combine

class View1ViewModel : ObservableObject{

var dataStorage = DataStorage()

func addBook (bookId:Int ,bookName : String){
dataStorage.cartArray.append(Book(bookId:bookId, bookName: bookName)) // Adding to global array
print(dataStorage.cartArray)
}

}
View1.swift
import SwiftUI
struct View1: View {

@ObservedObject var vwModel = View1ViewModel()
@EnvironmentObject var datastrg: DataStorage

var book:Book

var body: some View {

Text(book.bookName).font(.title)
Spacer()
Button(action: {
vwModel.addBook(bookId: book.bookId, bookName: book.bookName)

}, label: {
Text("Add Book to Cart")

.frame(maxWidth: .infinity, minHeight: 60)
.background(Color.red)
.foregroundColor(Color.white)
.font(.custom("OpenSans-Bold", size: 24))

})



}
}
View3.swift
import SwiftUI
struct View3: View {
@EnvironmentObject var datastorage : DataStorage
var body: some View {
NavigationView {
List(datastorage.cartArray,id:.id){book in

VStack{
Text(book.bookName)
.font(.custom("OpenSans-Bold", size: 20))

}

}

.navigationBarTitle(Text("Cart"), displayMode: .inline)
}
}
}

第一次调用addBook函数时,它打印为

[Example_App.Book(bookId: 1, bookName: "Catch-22")]

当我返回到这个View1并通过调用addBookfunc添加另一本书时它会将新对象添加到cartArray

[Example_App.Book(bookId: 3, bookName: "Stephen King")]

打印cartArray中的元素数为1 element而不是2 elements。当我转到View3并显示Books in列表时,cartArray显示为empty(0 elements)

我认为在ViewModel类中var dataStorage = dataStorage()有问题。每次都是新创建的,所以以前的值不会被存储。但我不明白如何保持它的状态如何在View3中显示列表?任何想法/建议都会有帮助的

您需要有一个DataStorage实例来传递。任何时候你写DataStorage()创建一个新的实例。

.environmentObject将允许您将该实例注入视图层次结构。然后,您可以使用@EnvironmentObject属性包装器在View中访问它。

View1中,我使用onAppearView1ViewModel上设置dataStorage属性——这意味着它必须在View1ViewModel上是可选的,因为它不会在init中设置。我避免在init中设置它的原因是因为@EnvironmentObject没有设置为Viewinit——它在渲染时被注入。

@main
struct Example_AppApp: App {
var dataStorage = DataStorage()

var body: some Scene {
WindowGroup {
ContentView().environmentObject(dataStorage)
}
}
}
class DataStorage: ObservableObject {
@Published var cartArray = [Book]()
}
struct ContentView: View {
@State var showSheetView = false

var body: some View {
NavigationView{

ListViewDisplay()
.navigationBarItems(trailing:
Button(action: {
self.showSheetView.toggle()
}) {
Image(systemName: "cart.circle.fill")
.font(Font.system(.title))
}
)
}.sheet(isPresented: $showSheetView) {
View3()
}
}
}
struct ListViewDisplay: View {
var book = [
Book(bookId: 1 ,bookName: "Catch-22"),
Book(bookId: 2 ,bookName: "Just-Shocking" ),
Book(bookId: 3 ,bookName: "Stephen King" ),
Book(bookId: 4,bookName: "A Gentleman in Moscow"),
]

var body: some View {
List(book, id: .id) { book in
Text(book.bookName)
NavigationLink(destination: View1(book: book)) {

}
}

}
}
struct Book: Codable, Identifiable {
var id:String{bookName}
var bookId : Int
var bookName: String

}
struct BookOption: Codable{
var name: String
var price: Int
}
class View1ViewModel : ObservableObject{

var dataStorage : DataStorage?

func addBook (bookId:Int ,bookName : String) {
guard let dataStorage = dataStorage else {
fatalError("DataStorage not set")
}
dataStorage.cartArray.append(Book(bookId:bookId, bookName: bookName)) // Adding to global array
print(dataStorage.cartArray)
}    
}
struct View1: View {

@ObservedObject var vwModel = View1ViewModel()
@EnvironmentObject var datastrg: DataStorage

var book:Book

var body: some View {

Text(book.bookName).font(.title)
Spacer()
Button(action: {
vwModel.addBook(bookId: book.bookId, bookName: book.bookName)

}, label: {
Text("Add Book to Cart")

.frame(maxWidth: .infinity, minHeight: 60)
.background(Color.red)
.foregroundColor(Color.white)
.font(.custom("OpenSans-Bold", size: 24))

})
.onAppear {
vwModel.dataStorage = datastrg
}
}
}
struct View3: View {
@EnvironmentObject var datastorage : DataStorage
var body: some View {
NavigationView {
List(datastorage.cartArray,id:.id){book in
VStack{
Text(book.bookName)
.font(.custom("OpenSans-Bold", size: 20))

}
}
.navigationBarTitle(Text("Cart"), displayMode: .inline)
}
}
}

你没有在任何地方调用你的函数addBook,添加一个onappear到你的view3调用函数,你的列表将填充数据。

最新更新