[英]SwiftUI ObservedObject not updating the view
I have this view which displays the name of a user.我有这个显示用户名的视图。
ClientViewModel
has a method loadClient()
which takes a Firestore document reference, loads the user and updates the model, which should update the view. ClientViewModel
有一个loadClient()
方法,它接受 Firestore 文档引用,加载用户并更新 model,它应该更新视图。 But the view is not being updated.但是视图没有更新。 In the
loadClient()
, displayName
is printed correctly, then I update the model, but the view is not being updated.在
loadClient()
中,正确打印了displayName
,然后我更新了 model,但视图没有被更新。 What am I doing wrong?我究竟做错了什么?
struct ItemView: View {
@EnvironmentObject var sessionStore: SessionStore
@ObservedObject var itemViewModel: ItemViewModel
@ObservedObject var clientViewModel = ClientViewModel()
func onAppear() {
itemViewModel.calcRoute() // this makes my client model null.
clientViewModel.loadClient(documentReference: itemViewModel.item.ownerReference)
}
var body: some View {
LoadingView(isShowing: $itemViewModel.isAnimating) {
VStack {
ItemDetailsView(itemViewModel: self.itemViewModel, clientViewModel: self.clientViewModel)
}
.navigationBarItems(trailing: EditButtonView(item: self.itemViewModel.item))
.onAppear(perform: self.onAppear)
}
}
}
struct ItemDetailsView: View {
@ObservedObject var itemViewModel: ItemViewModel
@ObservedObject var clientViewModel = ClientViewModel()
var body: some View {
Text(clientViewModel.client?.displayName ?? "nope")
.onAppear() {
self.clientViewModel.loadClient(documentReference: self.itemViewModel.item.ownerReference)
}
}
}
class ClientViewModel: ObservableObject {
@Published var client: Client?
@Published var error = ""
var firestoreService: FirestoreService = FirestoreService()
func loadClient(documentReference: DocumentReference) {
documentReference.addSnapshotListener { documentSnapshot, error in
guard let document = documentSnapshot else {
self.error = error!.localizedDescription
return
}
guard let data = document.data() else {
print("Document data was empty.")
return
}
self.client = Client(document: document)
print(self.client?.displayName) // this prints the name
}
}
}
class ItemViewModel: ObservableObject {
var firestoreService = FirestoreService()
@Published var item: Item
@Published var distance: String = "0 km"
@Published var travelTime = ""
@Published var route: MKRoute?
@Published var price: String = ""
@Published var error: String = ""
@Published var isAnimating: Bool = true
init(item: Item) {
self.item = item
}
// kte n servis
func calcRoute() {
let sourcePlacemark = MKPlacemark(coordinate: CLLocationCoordinate2D(
latitude: item.location.coordinate.latitude,
longitude: item.location.coordinate.longitude
))
let destinationPlacemark = MKPlacemark(coordinate: CLLocationCoordinate2D(
latitude: item.destination.coordinate.latitude,
longitude: item.destination.coordinate.longitude
))
let directionRequest = MKDirections.Request()
directionRequest.source = MKMapItem(placemark: sourcePlacemark)
directionRequest.destination = MKMapItem(placemark: destinationPlacemark)
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate { (response, error) in
self.isAnimating = false
guard let directionResponse = response else {
if let error = error {
self.error = error.localizedDescription
}
return
}
let route = directionResponse.routes[0]
self.route = route
self.travelTime = route.expectedTravelTime.asString(style: .abbreviated)
self.distance = "\((route.distance / 1000).rounded()) km"
let price = route.distance / 1000 //km
self.price = "\(price / 10)"
}
}
}
All @Published
properties must be updated on main queue to have UI updated.必须在主队列上更新所有
@Published
属性才能更新 UI。 Here is corrected variant这是更正的变体
func loadClient(documentReference: DocumentReference) {
documentReference.addSnapshotListener { documentSnapshot, error in
guard let document = documentSnapshot else {
DispatchQueue.main.async { // << here !!
self.error = error!.localizedDescription
}
return
}
guard let data = document.data() else {
print("Document data was empty.")
return
}
DispatchQueue.main.async { // << here !!
self.client = Client(document: document)
print(self.client?.displayName) // this prints the name
}
}
}
Solved by using @StateObject
instead of ObservedObject
.通过使用
@StateObject
而不是ObservedObject
解决。
@StateObject var clientViewModel = ClientViewModel()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.