SwiftUI:如何将 NavigationLink 放入地图标记的 MapPing 中

SwiftUI: How to put NavigationLink in MapPin or MapMarker

我已经解码了我的 JSON API 并成功地在地图上用 MapAnnotations 显示了位置并输入 NavigationLink 以查看其详细信息。但是不知何故,当我缩小地图以查看所有标记的位置时,突然间我的视图在模拟器和真实 iPhone 8 中变得非常滞后(可能是因为我在地图上有 100 多个注释?)。然后我尝试使用 MapMarker 并且视图变得更平滑,但现在问题是我不能将 NavigationLink 放在 MapMarkerMapPin 上。有没有合适的方法在地图上显示 marker/annotations 和 NavigationLink 而不会造成视图延迟??

这是我用于跟踪用户位置的 LocationManager 代码

import Foundation
import CoreLocation

class LocationManager: NSObject, ObservableObject {
    
    private let locationManager = CLLocationManager()
    @Published var location: CLLocation?
    
    override init() {
        super.init()
        
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = kCLDistanceFilterNone
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()
        locationManager.delegate = self
    }
    
}

extension LocationManager: CLLocationManagerDelegate {
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        guard let location = locations.last else { return }
        locationManager.stopUpdatingLocation()
        
        DispatchQueue.main.async {
            self.location = location
        }
        
    }
    
}

我的 ContentView 用于显示地图和显示注释

import SwiftUI
import MapKit
import Combine

struct ContentView: View {
    
    var body: some View {
        NavigationView{
            ServiceLocation()
        }
    }
}

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

extension MKCoordinateRegion {
    
    static var defaultRegion: MKCoordinateRegion {
        MKCoordinateRegion(center: CLLocationCoordinate2D.init(latitude: -0.789275, longitude: 113.921327), latitudinalMeters: 5000, longitudinalMeters: 5000)
    }
    
}

//MARK: MAP VIEW
struct ServiceLocation: View{
    
    @State var serviceLocations: [ServiceLocationJSON] = []
    @ObservedObject private var locationManager = LocationManager()
    @State private var region = MKCoordinateRegion.defaultRegion
    @State private var cancellable: AnyCancellable?
    
    private func setCurrentLocation() {
        cancellable = locationManager.$location.sink { location in
            region = MKCoordinateRegion(center: location?.coordinate ?? CLLocationCoordinate2D(), latitudinalMeters: 20000, longitudinalMeters: 20000)
        }
    }
    
    var body: some View{
        GeometryReader{ geometry in
            VStack{
                if locationManager.location != nil {
                    Map(coordinateRegion: $region, interactionModes: .all, showsUserLocation: true, userTrackingMode: .none, annotationItems: serviceLocations) { location in
                        MapAnnotation(coordinate: CLLocationCoordinate2D(latitude: location.LATITUDE, longitude: location.LONGITUDE)){
                            NavigationLink(destination: serviceLocationDetail(serviceLocations: location)){
                                Image(systemName: "mappin")
                                    .resizable()
                                    .scaledToFit()
                                    .frame(width: geometry.size.width / 15, height: geometry.size.height / 15)
                            }
                        }
                    }
                } else {
                    VStack{
                        Spacer()
                        ProgressView()
                        Spacer()
                    }
                }
            }.onAppear{
                setCurrentLocation()
                getServiceLocation(url: "https://my.api.mockaroo.com/latlong.json?key=e57d0e40"){ (serviceLocations) in
                    self.serviceLocations = serviceLocations
                }
            }
            .navigationTitle("Service")
            .navigationBarTitleDisplayMode(.inline)
            
        }
    }
}

//MARK: DETAIL VIEW
struct serviceLocationDetail: View{
    var serviceLocations: ServiceLocationJSON
    
    var body: some View{
        
        VStack{
            if serviceLocations.DEALER_NAME.isEmpty{
                VStack{
                    Spacer()
                    ProgressView()
                    Spacer()
                }
            }else{
                VStack(alignment: .leading, spacing: 10){
                    
                    Text(serviceLocations.DEALER_NAME)
                        .fontWeight(.medium)
                        .padding(.leading, 10)
                    Text(serviceLocations.DEALER_ADDRESS)
                        .padding(.leading, 10)
                    HStack(spacing: 5){
                        Image(systemName: "phone.fill")
                        Text(serviceLocations.PHONE)
                    }.padding(.leading, 10)
                    
                    Spacer()
                    
                }.navigationBarTitle(serviceLocations.DEALER_NAME)
            }
        }
        Spacer()
    }
}

//MARK: JSON MODEL
struct ServiceLocationJSON: Identifiable, Decodable{
    var id: Int
    var LATITUDE: Double
    var LONGITUDE: Double
    var DEALER_NAME: String
    var DEALER_ADDRESS: String
    var DEALER_PICTURE: String
    var PHONE: String
}

//MARK: DECODE JSON MODEL
func getServiceLocation(url: String, completion: @escaping ([ServiceLocationJSON])->()){
    let session = URLSession(configuration: .default)
    session.dataTask(with: URL(string: url)!){ (data, _, err) in
        if err != nil{
            print(err!.localizedDescription)
            return
        }
        do{
            let serviceLocations = try
                JSONDecoder().decode([ServiceLocationJSON].self, from: data!)
            completion(serviceLocations)
        }
        catch{
            print(error)
        }
    }.resume()
}

构建 Xcode 12 和 Swift 5

没关系,我刚刚解决了它。我只需要将 coordinateRegion: $region 更改为 coordinateRegion: .constant(region)