#ios #xcode #swiftui #mapkit #mklocalsearch
Вопрос:
У меня есть приложение, которое представляет собой приложение SwiftUI с жизненным циклом SwiftUI. Я настроил MKMapView как uiviewпредставляемый. Для одной из функций пользователь нажимает на два места на карте и вводит критерии поиска, чтобы найти места в регионе, ограниченном двумя нажатиями.
Карта работает, аннотации для отводов работают, и я получаю результаты от MKLocalSearch, но результаты неполные и не отражают регион, который я задал в запросе. В лучшем случае я получаю группу результатов примерно из центра региона. По краям почти ничего или почти ничего. Кажется, не имеет значения, создаю ли я круглую или прямоугольную область. И, похоже, не имеет значения, насколько велик мой регион. Я просто не получаю достоверных результатов в конечных точках.
Я удалил все, кроме самого необходимого, чтобы показать проблему, поэтому этот код можно запустить для демонстрации. Поместите курсор в текстовое поле и нажмите «Возврат», затем коснитесь шестеренки, чтобы распечатать результаты на консоли
Вот карта:
struct MapView: UIViewRepresentable {
typealias UIViewType = MKMapView
@State private var myMapView: MKMapView?
@State private var sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
class Coordinator: NSObject, MKMapViewDelegate {
var control: MapView
init(_ control: MapView) {
self.control = control
}
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
if let annotationView = views.first {
if let annotation = annotationView.annotation {
if annotation is MKUserLocation {
let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 5000, longitudinalMeters: 5000)
mapView.setRegion(region, animated: true)
}//if user
}//if annotation
}//if views first
}//did add
}//class
func makeUIView(context: Context) -> MKMapView {
let map = MKMapView()
map.showsUserLocation = true
map.delegate = context.coordinator
DispatchQueue.main.async {
self.myMapView = map
}
return map
}//make ui view
func makeCoordinator() -> Coordinator {
Coordinator(self)
}//coord
func updateUIView(_ view: MKMapView, context: Context) {
}//update ui view
}//struct
И представление содержимого с вспомогательными файлами:
struct ContentView: View {
@State private var search = "Coffee"
@State private var myLandmarks: [MyLandmark] = [MyLandmark]()
@State private var mapView: MapView?
var body: some View {
NavigationView {
ZStack(alignment: .top) {
MapView()
.ignoresSafeArea()
TextField("Search", text: $search, onEditingChanged: { _ in })
{
self.getNearbyMyLandmarks()
}
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
.offset(y: -20)
} //z
.navigationBarItems(leading: Button(action: {
self.printMyLandmarks()
}) {
Image(systemName: "gear")
.resizable()
.frame(width: 25, height: 25, alignment: .center)
}, trailing: Button(action: {
self.search = "Coffee"
}) {
Image(systemName: "arrow.counterclockwise.circle")
.resizable()
.frame(width: 25, height: 25, alignment: .center)
}
)//nav bar items
}//nav
.navigationViewStyle(StackNavigationViewStyle())
}//body
}// content view
private extension ContentView {
private func getNearbyMyLandmarks() {
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = search
let sfRegion = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194), latitudinalMeters: 100000, longitudinalMeters: 100000)
request.region = sfRegion
let search = MKLocalSearch(request: request)
search.start { (response, error) in
if let response = response {
let mapItems = response.mapItems
self.myLandmarks = mapItems.map {
MyLandmark(mapItem: $0)
}
}
}
}//get nearby landmarks
//used of testing only
func printMyLandmarks() {
let sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
for m in 0..<self.myLandmarks.count {
print(myLandmarks[m].name ", " distanceFromCenter(center: sfCoord, site: myLandmarks[m].coordinate))
}
}//print my landmarks
func distanceFromCenter(center: CLLocationCoordinate2D, site: CLLocationCoordinate2D) -> String {
let centerLocation = CLLocation(latitude: center.latitude, longitude: center.longitude)
let siteLocation = CLLocation(latitude: site.latitude, longitude: site.longitude)
let distanceInMeters: Double = siteLocation.distance(from: centerLocation)
let distanceString = String(format: "%.0f", distanceInMeters)
return distanceString
}//distance from center
}//extension Content View
struct MyLandmark {
let mapItem: MKMapItem
var id: UUID {
return UUID()
}
var name: String {
self.mapItem.placemark.name ?? "No Name Listed"
}
var coordinate: CLLocationCoordinate2D {
self.mapItem.placemark.coordinate
}
}//struct my landmark
The console shows the following for two different region spans (line 119)
First list with 100k meters:
Peet’s Coffee, 31672
Hippie’s Brew, 31796
The Early Bird Coffee Co, 31707
Starbucks, 31573
Anna’s Family Coffee Shop, 32050
Aj’s Coffee, 32959
Brewja Coffee, 26822
Starbucks, 31480
Cafe 4, 30126
Eon Coffee, 31241
Frodo Joe’s Coffee amp; Tea, 28427
Peet’s Coffee, 31642
Snappy’s Cafe, 31613
Starbucks, 32015
Atlas Cafe, 31855
Dunkin’, 32050
Zocalo Coffeehouse, 24113
Starbucks, 31334
Pampas Cafe, 31647
Starbucks, 30666
Donut Express, 32026
Starbucks, 32827
Starbucks, 30370
Starbucks, 29164
Valley Java Organic Coffee amp; Tea, 30348
Second list with region at 1000 meters:
Симплекситея, 237 Кофе В Голубой Бутылке, 371 Ритуальная Кофейная Жаровня, 455 Кофейня Mavelous И Маленькая Сковородка, 122 Городских Ритуала, 576 Кафе All Star, 412 Кофе Peet’s, 272 Кафе Mercury, 445 Кумаика, 317 Жаровен Для Кофе С Секстантом, 633 Кафе Planet SF, 293 Кофе Philz, 734 Кофе С Бокалом, 985 Кафе Javalencia, 115 Кафе Нины, 219 Булочная La, 526 Кафе Десерта Ная, 549 Кофе С Четырьмя Бочонками, 900 Культур Кофе, Кафе 436 В, 603 Starbucks, 309 Starbucks, 256 Пончиков Джонни, 564 Рынок и пекарня Фокачча, 645
Я надеюсь, что упускаю здесь что-то простое. Результаты, которые я получаю, очевидно, бесполезны. Буду признателен за любые рекомендации.