Как я могу сделать инструкции по маршруту карты интерактивными в SwiftUI?

У меня есть простая карта, сделанная с помощью «чистого» SwiftUI. Существует панель поиска для поиска места, и когда я нажимаю кнопку «Перейти», отображаются инструкции о том, как перейти в это место из определенного места. Он показывает его под картой, в поле «Введите пункт назначения». Что я хочу сделать, так это сделать эти инструкции кликабельными. Когда я нажимаю на каждую из инструкций, она должна увеличиваться в том конкретном месте, где происходит инструкция. Сейчас это только список текста. Можно ли это сделать без использования UIViewRepresentable? И как я могу это сделать?

я пробовал с

.onTapGesture {
                    region.span = MKCoordinateSpan(latitudeDelta: region.span.latitudeDelta/2, longitudeDelta: region.span.longitudeDelta/2)
                }

но он масштабируется в одном и том же месте при каждой инструкции, которую я нажимаю.

ContentView

struct Location: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}

struct RouteSteps: Identifiable {
    let id = UUID()
    let step: String
}
    
struct ContentView: View {
@State private var searchBar: String = ""
    @State private var home = CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081)
    @State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
    @State var routeSteps: [RouteSteps] = [RouteSteps(step: "Enter a destination")]
    @State var annotations = [Location(name: "Ankara", coordinate: CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081))]
    var body: some View {
        VStack{
             HStack {
            TextField("", text: $searchBar)
            Button("Go") {
                findNewLocation()
            }
            .frame(width: 35, height: 35)
            .foregroundColor(Color.white)
            .background(Color.blue)
            .cornerRadius(5)
             }.textFieldStyle(.roundedBorder).colorInvert()
            Map(coordinateRegion: $region, annotationItems: annotations){ item in
                MapMarker(coordinate: item.coordinate)
            }.frame(width: 400, height: 300)
            List(routeSteps) { r in
                Text(r.step)
            }

функция маршрута в ContentView

func findNewLocation(){
    let searchResult = searchBar
    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString(searchResult, completionHandler:
    {(placemarks, error) -> Void in
        if ((error) != nil){
            print("error at geocode")
        }
        if let placemark = placemarks?.first {
            let coordinates : CLLocationCoordinate2D = placemark.location!.coordinate
            region = MKCoordinateRegion(center: coordinates, span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
            annotations.append(Location(name: placemark.name!, coordinate: coordinates))
            let request = MKDirections.Request()
            request.source = MKMapItem(placemark: MKPlacemark(coordinate: home, addressDictionary: nil))
            request.destination = MKMapItem(placemark: MKPlacemark(coordinate: coordinates, addressDictionary: nil))
            request.requestsAlternateRoutes = false 
            request.transportType = .automobile 
    
            let directions = MKDirections(request: request)
            directions.calculate(completionHandler: { response, error in
                for route in (response?.routes)! {
                    self.routeSteps = []
                    for step in route.steps {
                        self.routeSteps.append(RouteSteps(step: step.instructions))
                    }
                }
            })
        }
    })
}

Проверьте эти два вопроса: stackoverflow.com/questions/11713788/…stackoverflow.com/questions/33431482/…

realitystruck 16.03.2022 13:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Да, но вы должны перестать выбрасывать данные. MKRoute.Steps на самом деле дает вам всю необходимую информацию, поэтому сначала настройте RouteSteps, чтобы принять MKRoute.Steps:

struct RouteSteps: Identifiable {
    let id = UUID()
    let step: MKRoute.Step
}

Затем в вашей функции findNewLocation():

func findNewLocation(){
    ...
    directions.calculate(completionHandler: { response, error in
                // I used a guard statement to get rid of your force unwrap.
                // NEVER force unwrap in a situation like this.
                // Implement error handling here
                guard let response = response else { return } 
                for route in response.routes {
                    // Map the MKRoute.Steps to your struct
                    self.routeSteps = route.steps.map( { RouteSteps(step: $0) } )
                }
            })
    ...

}

Затем в основной части вашего ContentView:

struct ContentView: View {
    ...

    var body: some View {
        ...
            List(routeSteps) { routeStep in
                // Pull your instructions out here
                Text(routeStep.step.instructions)
                    .onTapGesture {
                        // The MKRoute.Step contains an overlay polyline for MKMapKit.
                        // We can't use that in SwiftUI maps yet, but the polyline contains a
                        // boundingMapRect that we can use to change the region shown on the map
                        // with the MKCoordinateRegion(_ MKMapRect) initializer. Setting the region
                        // to the insturction's polyline boundingMapRect does exactly what you want.
                        region = MKCoordinateRegion(routeStep.step.polyline.boundingMapRect)
                    }
            }
        ...
}

Спасибо за ответ. Я сейчас в этой строке @State var routeSteps: [RouteSteps] = [RouteSteps(step: "Enter a destination")] получаю эту ошибку: Невозможно преобразовать значение типа «String» в ожидаемый тип аргумента «MKRoute.Step», вы можете мне помочь?

Eda 16.03.2022 15:30

Извините, я изменил это в своем коде на @State var routeSteps: [RouteSteps] = []. Там есть лучшие способы сделать подсказку.

Yrb 16.03.2022 16:42

Другие вопросы по теме

Похожие вопросы