1

我试图制作一个带有文本字段的应用程序,让用户输入一个位置,使用 MKLocalSearchCompleter 来完成搜索。之后,我想获得坐标并在 MapKit 上显示。但是,我无法使用地理编码器获取坐标。

class LocationSearchService: NSObject, ObservableObject, MKLocalSearchCompleterDelegate {
    @Published var searchQuery = ""
    var completer: MKLocalSearchCompleter
    @Published var completions: [MKLocalSearchCompletion] = []
    var cancellable: AnyCancellable?
    
    override init() {
        completer = MKLocalSearchCompleter()
        super.init()
        cancellable = $searchQuery.assign(to: \.queryFragment, on: self.completer)
        completer.delegate = self
    }
    
    func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
        self.completions = completer.results
    }
}

位置管理器如下:

class LocationManager: NSObject, ObservableObject {
    
    private let locationManager = CLLocationManager()
    private let geocoder = CLGeocoder()
    
    let objectWillChange = PassthroughSubject<Void, Never>()
    
    @Published var status: CLAuthorizationStatus? {
        willSet { objectWillChange.send() }
    }
    
    @Published var location: CLLocation? {
        willSet { objectWillChange.send() }
    }
    
    override init() {
        super.init()
        
        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
    }
    
    @Published var placemark: CLPlacemark? {
        willSet { objectWillChange.send() }
    }
    
    private func lookupLocation() {
        guard let location = self.location else { return }
        geocoder.reverseGeocodeLocation(location, completionHandler: { (places, error) in
            if error == nil {
                self.placemark = places?[0]
            } else {
                self.placemark = nil
            }
        })
    }
    
    // !!! This is the function I would like to use to get the Coordinate from the address obtained from LocationSearchService
    func getCoordinate(address: String) {
        geocoder.geocodeAddressString(address, completionHandler: { (places, error) in
            if error == nil {
                self.placemark = places?[0]
                self.location = self.placemark?.location
            } else {
                self.placemark = nil
                self.location = nil
            }
        })
    }
    
}

extension LocationManager: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        self.status = status
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return } //.first or .last?
                    
        self.location = location
        self.lookupLocation()
    }
}

内容视图如下:

struct ContentView: View {
    
    @State private var location: String = ""
    
    @ObservedObject var lm = LocationManager()
    
    private let completer = MKLocalSearchCompleter()
        
    @ObservedObject var locationSearchService = LocationSearchService()
    
    var body: some View {
        
        NavigationView {
            VStack {
                AddressSearchBar(text: $locationSearchService.searchQuery)
                List(locationSearchService.completions, id: \.self) { completion in
                    VStack(alignment: .leading) {
                        Text(completion.title)    
                    
                        // Error here, I cannot translate the address to location 
                        //Text(lm.getCoordinate(address: completion.title))
                    }
                }.navigationTitle("Search Location")
            }
        }

这里有几个问题:

  1. 我想将用户选择的项目(我在这里未能实现)转换为地址(completion.title)——即,需要获得用户对建议项目的选择。
  2. 我想将建议中找到的地址转换为坐标,以便在 MapView 上进行标记。
4

0 回答 0