SwiftUI - 尽管使用@Published 和@ObservedObject,但视图不会更新
SwiftUI - View doesn't update despite using @Published and @ObservedObject
我在使用 SwiftUI 更新我的应用程序的主页视图时遇到了问题。
所以,我有一个 Dog 结构体 (Dog.swift) :
struct Dog: Identifiable {
var id = UUID()
var name: String
var race: String
var age: Int
var gender: String
var sterile: Bool
var pictureURL: String
var location: String
var dogFriendly: Bool
var catFriendly: Bool
var childFriendly: Bool
var needsGarden: Bool
var isClean: Bool
}
我的目标是在 AddView.swift:
中按下这个按钮
@ObservedObject var viewModel = AddViewModel()
************** LONG UI CODE *******************
.navigationBarItems(trailing:
Button("Publish") {
viewModel.dogs.append(Dog(name: self.name, race: races[selectedRace], age: self.age, gender: genders[selectedGender], sterile: self.isSterile, pictureURL: "", location: "", dogFriendly: self.isDogFriendly, catFriendly: self.isCatFriendly, childFriendly: self.isChildFriendly, needsGarden: self.needsGarden, isClean: self.isClean))
print(viewModel.dogs)
})
将 dogs 添加到 AddViewModel.swift:
中的 Dog 数组
class AddViewModel: ObservableObject {
@Published var dogs: [Dog] = []
}
然后在 CardView 中显示信息:
struct CardView: View {
//MARK: - Properties
@State var dog: Dog
//MARK: - View
var body: some View {
******* LONG UI CODE ********
}
并在我的 HomeView 中显示这些 CardView:
struct HomeView: View {
@ObservedObject var viewModel = AddViewModel()
var body: some View {
ScrollView {
VStack {
ForEach(viewModel.dogs) { dog in
CardView(dog: dog) // this doesn't work
Text(dog.name) // this doesn't work neither
}
}
}
}
}
有人可以帮我解决这个问题并就如何进行提供建议吗?
感谢您的慷慨帮助!
将@State 更改为@Bindig 将修复它。
卡片视图:
struct CardView: View {
//MARK: - Properties
@Binding var dog: Dog
//MARK: - View
var body: some View {
******* LONG UI CODE ********
}
我想你想在 AddView
内追加 Dog
的 Array
,并在 HomeView
内显示更新后的数据。因此,您刚刚在每个视图中分别声明了 AddViewModel
的实例。视图中的两个实例不会相互观察。为了解决这个问题,我更喜欢使用 Singleton
模式。这是我的示例代码。
struct ContentView: View {
@ObservedObject private var viewModel: AddViewModel = .sharedInstance
@State private var showSheet = false
var body: some View {
NavigationView {
ScrollView {
ForEach(viewModel.dogs) { dog in
Text(dog.name)
.frame(height: 25)
}
}
.navigationTitle("DogZ")
.navigationBarItems(leading: Button(action: {
showSheet.toggle()
}, label: {
Text("Show")
}))
}
.sheet(isPresented: $showSheet, content: {
AddView()
})
}
}
struct AddView: View {
@ObservedObject private var viewModel: AddViewModel = .sharedInstance
@Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView {
Text("Sheet Add View")
.navigationBarItems(trailing: Button(action: {
viewModel.dogs.append(Dog(name: "Blacky"))
presentationMode.wrappedValue.dismiss()
}, label: {
Text("Add")
}))
}
}
}
class AddViewModel: ObservableObject {
@Published var dogs = [Dog]()
static var sharedInstance = AddViewModel()
}
struct Dog: Identifiable {
var id = UUID()
var name: String
}
我在使用 SwiftUI 更新我的应用程序的主页视图时遇到了问题。
所以,我有一个 Dog 结构体 (Dog.swift) :
struct Dog: Identifiable {
var id = UUID()
var name: String
var race: String
var age: Int
var gender: String
var sterile: Bool
var pictureURL: String
var location: String
var dogFriendly: Bool
var catFriendly: Bool
var childFriendly: Bool
var needsGarden: Bool
var isClean: Bool
}
我的目标是在 AddView.swift:
中按下这个按钮@ObservedObject var viewModel = AddViewModel()
************** LONG UI CODE *******************
.navigationBarItems(trailing:
Button("Publish") {
viewModel.dogs.append(Dog(name: self.name, race: races[selectedRace], age: self.age, gender: genders[selectedGender], sterile: self.isSterile, pictureURL: "", location: "", dogFriendly: self.isDogFriendly, catFriendly: self.isCatFriendly, childFriendly: self.isChildFriendly, needsGarden: self.needsGarden, isClean: self.isClean))
print(viewModel.dogs)
})
将 dogs 添加到 AddViewModel.swift:
中的 Dog 数组class AddViewModel: ObservableObject {
@Published var dogs: [Dog] = []
}
然后在 CardView 中显示信息:
struct CardView: View {
//MARK: - Properties
@State var dog: Dog
//MARK: - View
var body: some View {
******* LONG UI CODE ********
}
并在我的 HomeView 中显示这些 CardView:
struct HomeView: View {
@ObservedObject var viewModel = AddViewModel()
var body: some View {
ScrollView {
VStack {
ForEach(viewModel.dogs) { dog in
CardView(dog: dog) // this doesn't work
Text(dog.name) // this doesn't work neither
}
}
}
}
}
有人可以帮我解决这个问题并就如何进行提供建议吗?
感谢您的慷慨帮助!
将@State 更改为@Bindig 将修复它。
卡片视图:
struct CardView: View {
//MARK: - Properties
@Binding var dog: Dog
//MARK: - View
var body: some View {
******* LONG UI CODE ********
}
我想你想在 AddView
内追加 Dog
的 Array
,并在 HomeView
内显示更新后的数据。因此,您刚刚在每个视图中分别声明了 AddViewModel
的实例。视图中的两个实例不会相互观察。为了解决这个问题,我更喜欢使用 Singleton
模式。这是我的示例代码。
struct ContentView: View {
@ObservedObject private var viewModel: AddViewModel = .sharedInstance
@State private var showSheet = false
var body: some View {
NavigationView {
ScrollView {
ForEach(viewModel.dogs) { dog in
Text(dog.name)
.frame(height: 25)
}
}
.navigationTitle("DogZ")
.navigationBarItems(leading: Button(action: {
showSheet.toggle()
}, label: {
Text("Show")
}))
}
.sheet(isPresented: $showSheet, content: {
AddView()
})
}
}
struct AddView: View {
@ObservedObject private var viewModel: AddViewModel = .sharedInstance
@Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView {
Text("Sheet Add View")
.navigationBarItems(trailing: Button(action: {
viewModel.dogs.append(Dog(name: "Blacky"))
presentationMode.wrappedValue.dismiss()
}, label: {
Text("Add")
}))
}
}
}
class AddViewModel: ObservableObject {
@Published var dogs = [Dog]()
static var sharedInstance = AddViewModel()
}
struct Dog: Identifiable {
var id = UUID()
var name: String
}