[英]SwiftUI ObservedObject not updating the view
我有这个显示用户名的视图。 ClientViewModel
有一个loadClient()
方法,它接受 Firestore 文档引用,加载用户并更新 model,它应该更新视图。 但是视图没有更新。 在loadClient()
中,正确打印了displayName
,然后我更新了 model,但视图没有被更新。 我究竟做错了什么?
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)"
}
}
}
必须在主队列上更新所有@Published
属性才能更新 UI。 这是更正的变体
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
}
}
}
通过使用@StateObject
而不是ObservedObject
解决。
@StateObject var clientViewModel = ClientViewModel()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.