I am using MKLocalSearch to allow users to search for their city. However, when I try the code I only receive results in the US. Also I receive a lot of results that include stores etc. I added the filters in func completerDidUpdateResults(_ completer: MKLocalSearchCompleter)
to get rid of results that are not cities. This works but I feel like this may fail for certain places. I tried adding the code below but that didn't work. I'd appreciate any help.
let worldRegion = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 0, longitude: 0),
span: MKCoordinateSpan(latitudeDelta: 180, longitudeDelta: 360))
self.searchCompleter.region = worldRegion
import Foundation
import Combine
import MapKit
class LocationService: NSObject, ObservableObject {
enum LocationStatus: Equatable {
case idle
case noResults
case isSearching
case error(String)
case result
}
@Published var queryFragment: String = ""
@Published private(set) var status: LocationStatus = .idle
@Published private(set) var searchResults: [MKLocalSearchCompletion] = []
private var queryCancellable: AnyCancellable?
private let searchCompleter: MKLocalSearchCompleter!
init(searchCompleter: MKLocalSearchCompleter = MKLocalSearchCompleter()) {
self.searchCompleter = searchCompleter
super.init()
self.searchCompleter.delegate = self
queryCancellable = $queryFragment
.receive(on: DispatchQueue.main)
.debounce(for: .milliseconds(250), scheduler: RunLoop.main, options: nil)
.sink(receiveValue: { fragment in
self.status = .isSearching
if !fragment.isEmpty {
self.searchCompleter.queryFragment = fragment
} else {
self.status = .idle
self.searchResults = []
}
})
}
}
extension LocationService: MKLocalSearchCompleterDelegate {
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
self.searchResults = completer.results.filter { result in
if !result.title.contains(",") {
return false
}
if result.title.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil {
return false
}
if result.subtitle.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil {
return false
}
return true
}
self.status = completer.results.isEmpty ? .noResults : .result
}
func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
self.status = .error(error.localizedDescription)
}
}
import SwiftUI
import MapKit
struct locView: View {
@StateObject var locationService = LocationService()
var body: some View {
VStack {
Form {
Section(header: Text("Location Search")) {
ZStack(alignment: .trailing) {
TextField("Search", text: $locationService.queryFragment)
if locationService.status == .isSearching {
Image(systemName: "clock")
.foregroundColor(Color.gray)
}
}
}
Section(header: Text("Results")) {
List {
Group { () -> AnyView in
switch locationService.status {
case .noResults: return AnyView(Text("No Results"))
case .error(let description): return AnyView(Text("Error: \(description)"))
default: return AnyView(EmptyView())
}
}.foregroundColor(Color.gray)
ForEach(locationService.searchResults, id: \.self) { completionResult in
Text(completionResult.title)
}
}
}
}
}
}
}