Ios SwiftUI ObservedObject未更新视图
我有一个显示用户名的视图Ios SwiftUI ObservedObject未更新视图,ios,swift,swiftui,Ios,Swift,Swiftui,我有一个显示用户名的视图ClientViewModel有一个方法loadClient(),该方法获取Firestore文档引用,加载用户并更新模型,该模型应更新视图。但是视图没有被更新。在loadClient()中,正确打印了displayName,然后我更新了模型,但没有更新视图。我做错了什么 struct ItemView: View { @EnvironmentObject var sessionStore: SessionStore @ObservedObject var
ClientViewModel
有一个方法loadClient()
,该方法获取Firestore文档引用,加载用户并更新模型,该模型应更新视图。但是视图没有被更新。在loadClient()
中,正确打印了displayName
,然后我更新了模型,但没有更新视图。我做错了什么
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)"
}
}
}
必须更新主队列上所有已发布的属性,才能更新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
}
}
}
func加载客户端(documentReference:documentReference){
documentReference.addSnapshotListener{documentSnapshot,出现错误
guard let document=documentSnapshot else{
DispatchQueue.main.async{/通过使用@StateObject
而不是ObservedObject
解决
@StateObject var clientViewModel = ClientViewModel()
当我删除所有与firebase相关的代码时,它按预期工作。但是为什么我要在方法中正确打印名称?将客户端属性的更新发送到主队列不工作,名称仍然没有显示在视图中。不工作,名称仍然没有显示在视图中。确定我找到了哪一行正在断开它。在我的ItemView(ItemDetailsView的父级)中,onAppear()正在运行这个calcRoute()方法。如果我对它进行注释,它会工作,当我进行更近距离的拍摄时,首先显示名称,然后在calcRoute完成后,它会变为零。