Создание MapView из декодированных координат — swift

#ios #swift #dictionary #view #mapkit

#iOS #swift #словарь #Вид #mapkit

Вопрос:

Я настраиваю MapView с пользовательскими координатами. Вот мой код на данный момент

 var coordModel: AirportModel?

struct MapView: View {
    
    
    
    @Binding private var lat: Double
    @Binding private var lon: Double

    private let initialLatitudinalMetres: Double = coordModel?.airportLat ?? 0
    private let initialLongitudinalMetres: Double = coordModel?.airportLong ?? 0

    @State private var span: MKCoordinateSpan?

    init(lat: Binding<Double>, lon: Binding<Double>) {
        _lat = lat
        _lon = lon
    }

    private var region: Binding<MKCoordinateRegion> {
        Binding {
            let centre = CLLocationCoordinate2D(latitude: lat, longitude: lon)

            if let span = span {
                return MKCoordinateRegion(center: centre, span: span)
            } else {
                return MKCoordinateRegion(center: centre, latitudinalMeters: initialLatitudinalMetres, longitudinalMeters: initialLongitudinalMetres)
            }
        } set: { region in
            lat = region.center.latitude
            lon = region.center.longitude
            span = region.span
        }
    }

    var body: some View {
        Map(coordinateRegion: region)
    }
}
  

В модели AirportModel есть фрагмент данных, декодированный в двойной форме, называемый «широта» и «долгота». Я просто пытаюсь передать эти данные в представление после их декодирования. Вот мое тело представления:

 var body: some View {
    
        ScrollView{
            MapView(lat: <#Binding<Double>#>, lon: <#Binding<Double>#>)
                .frame(height: 250)
                .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
}
  

Я пробовал ставить coordModel?.широта и координатная модель?. долгота для широты и долготы, а также установка переменных над вызовом. Я не совсем уверен, куда теперь идти.

Примечание: я декодирую кучу данных JSON, и каждый пользовательский запрос приводит к разным широтам / широтам (более 10000 потенциальных ответов). Еще раз спасибо!

Комментарии:

1. Содержит ли ваша модель аэропорта такие фигуры, как здания и магазины, или только точки? Если вы хотите отображать фигуры на карте, забудьте о SwiftUI. SwiftUI Maps не имеет наложений. Вернитесь к старому доброму MKMapKit, если вам нужны наложения.

2. Он не должен показывать ничего, кроме последней и длинной группы координат

3. То, что вы ищете, — это аннотации. Это простое введение о том, как показывать аннотации: medium.com/better-programming /…

4. Это отличная статья, спасибо. Тем не менее, мне все еще нужно выяснить, как передать декодированные значения широты и длины из вызова api и динамически вводить их в единый вид, который отображает отчет о погоде для этого аэропорта — не то, что я могу жестко запрограммировать из-за огромного количества возможных аэропортов.

5. Не отвечаю на ваши вопросы: данные о погоде могут отображаться в виде фрагментов карты (не то, что вы делаете сейчас) И карты SwiftUI не могут этого сделать, поскольку им вообще не хватает TileOverlays и overlays. Если есть хотя бы небольшой шанс, что вам это нужно, используйте старый MKMapKit .

Ответ №1:

Используйте модель, которая является ObservableObject :

 import Combine
import MapKit

class MapModel: ObservableObject {
    
    var region: MKCoordinateRegion = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 48.687330584, longitude: 9.219832454),
        latitudinalMeters: 1000000,
        longitudinalMeters: 1000000
    ) {
        willSet {
            self.objectWillChange.send()
        }
    }
    
    // MARK: - test code change center evey 10 seconds
    
    init() {
        
        self.timer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { timer in
            self.testIndex  = 1
            self.testIndex %= self.testCoordinates.count
            let newCenter = self.testCoordinates[self.testIndex]
            let oldSpan = self.region.span
            
            DispatchQueue.main.async {
                self.region = MKCoordinateRegion(center: newCenter, span: oldSpan)
            }
        }
    }
    
    let testCoordinates = [
        CLLocationCoordinate2D(latitude: 48.687330584, longitude: 9.219832454), // STR
        CLLocationCoordinate2D(latitude: 41.297445, longitude: 2.0832941),  // BCN
    ]
    var testIndex: Int = 0
    
    var timer: Timer? = nil
    
    
}
  

затем создайте представление, которое наблюдает за вашей моделью

 import SwiftUI
import MapKit

struct ContentView: View {
    @ObservedObject private var mapModel = MapModel()

    var body: some View {
        Map(coordinateRegion: $mapModel.region)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
  

Для тестирования я использовал таймер, который имитирует обновленные данные с сервера.

Если вам нужны аннотации, добавьте их в модель и не забудьте self.objectWillChange.send() , если вы их измените.

Комментарии:

1. Как я могу изменить этот код для обновления при вводе нового запроса и выполнять один и тот же вызов, но каждый раз с другим поисковым запросом? См . avwx.docs.apiary.io/#reference/0/station /… для API, из которого я пытаюсь получить широту / длину.

2. просто установите MapModel.region, и карта автоматически обновится