正如标题中所说,3个@AppStorage
变量中有2个在第一次没有更新。所以,当视图被关闭时,我必须重新打开它,然后在第二次关闭时,它们都被更新了。准确地说,第一次只有storedCityName
被更新了。
这里的观点:
import SwiftUI
struct SearchView: View {
@Environment(\.dismiss) private var dismiss
@EnvironmentObject private var searchManager: SearchManager
@AppStorage("storedUserLatitude") private var storedUserLatitude: Double?
@AppStorage("storedUserLongitude") private var storedUserLongitude: Double?
@AppStorage("storedCityName") private var storedCityName: String?
var body: some View {
VStack {
TextField("", text: $searchManager.search)
ForEach(searchManager.searchResults, id: \.self) { result in
HStack {
VStack {
Text(result.title)
Text(result.subtitle)
}
}
.onTapGesture { update(result.title) }
}
}
}
private func update(_ city: String) {
searchManager.searchLocation(city)
storedUserLatitude = searchManager.userLocation?.coordinate.latitude
storedUserLongitude = searchManager.userLocation?.coordinate.longitude
storedCityName = city
dismiss()
}
}
字符串
这是经理:
import Foundation
import MapKit
import Combine
class SearchManager: NSObject, ObservableObject, MKLocalSearchCompleterDelegate {
private let completer = MKLocalSearchCompleter()
@Published var search = ""
@Published var searchResults = [MKLocalSearchCompletion]()
@Published var userLocation: CLLocation?
private var publisher: AnyCancellable?
override init() {
super.init()
completer.delegate = self
completer.resultTypes = .address
publisher = $search
.receive(on: RunLoop.main)
.sink(receiveValue: { string in
self.completer.queryFragment = string
})
}
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
searchResults = completer.results
}
func searchLocation(_ city: String) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(city) { placemarks, error in
guard let placemark = placemarks?.first else { return }
self.userLocation = placemark.location
}
}
}
型
我真的不明白为什么它在第二次尝试时有效,但在第一次尝试时无效。
我还尝试用DispatchQueue.main.asyncAfter(deadline: .now() + 2) { dismiss() }
延迟dismiss
,看看@AppStorage
变量是否需要时间更新,但它没有改变任何东西。
你知道发生什么事了吗?
谢谢,提前!
1条答案
按热度按时间yrwegjxp1#
这里的真实的问题是,您使用
searchManager.searchLocation(city
)调用了反向地理编码器,它使用了一个reverse geocoding函数来执行反向地理编码。当您向它传递一个块来设置搜索管理器中的值时,SearchView
中的代码并没有等待该信息。在第二次尝试时,您的SearchManager环境对象有时间使用第一次尝试的地理编码进行更新。
你应该考虑更新
searchLocation
,以确保它只在地理编码发生后运行update
中的后续代码。一种方法是允许它接收一个块:字符串
还有更简洁的方法,您需要正确地处理错误路径,但希望这能给您正确的想法。