SwiftUI 地图显示标注

6

我决定将MKMapView包装成UIViewRepresentable转换为SwiftUI中的新 Map()

我能够成功地在Map()中显示一个MKMapRect,但我无法显示两个MKPointAnnotation。而且我的路线也没有显示出来。

它要求我提供一个RandomAccessCollection和一个(Identifiable) -> MapAnnotationProtocol>,但我不知道应该放什么。

你有什么想法可以放在(Identifiable) -> MapAnnotationProtocol中?

import SwiftUI
import MapKit

extension MKPointAnnotation: Identifiable { }

struct ItemView: View {
    @ObservedObject var itemViewModel: ItemViewModel
    @State var coll = [MKPointAnnotation]()
    
    func onAppear() {
        let requestAnnotation = MKPointAnnotation()
        requestAnnotation.coordinate = CLLocationCoordinate2D(latitude: 46.2004781, longitude: 6.1346497)
        requestAnnotation.title = "Package"
        
        let destinationAnnotation = MKPointAnnotation()
        destinationAnnotation.coordinate = CLLocationCoordinate2D(latitude: 47.1420446, longitude: 9.5204032)
        destinationAnnotation.title = "Destination"
        
        coll.append(requestAnnotation)
        coll.append(destinationAnnotation)
    }
    
    var body: some View {
        VStack {
            if let mapRect = itemViewModel.route?.polyline.boundingMapRect {
                Map(mapRect: .constant(mapRect), annotationItems: coll) { point in
                  MapAnnotation(coordinate: point.coordinate) {
                      Text(point.title ?? "")
                  }
                }
            }
        }
        .onAppear(perform: self.onAppear)
    }
    
}
4个回答

3

在我看来,MapAnnotation 要求你实现将在地图上呈现的整个视图,因此如果你想要红色标记和一些文本,你将不得不自己创建该标记(例如使用 SF 符号的 Image 实例)。当然,它看起来不如 MapMarker 中的标记好看,但至少是一个开始。

Map(coordinateRegion: .constant(mapRect), annotationItems: coll) { annotationItem in
  MapAnnotation(coordinate: annotationItem.coordinate) {
    VStack {
      Group {
        Image(systemName: "mappin.circle.fill")
          .resizable()
          .frame(width: 30.0, height: 30.0)
        Circle()
          .frame(width: 8.0, height: 8.0)
      }
      .foregroundColor(.red)
      Text(annotationItem.title)
    }
  }
}

3

不再需要使用MKPointAnnotation。目前,在 Xcode 12.0 Beta 中,SwiftUI 提供了三个结构体来满足MapAnnotationProtocol

  • MapAnnotation
  • MapMarker
  • MapPin

RandomAccessCollection 应该是任何采用 Identifiable 的对象集合(数组即可),这些作为 Map 初始化器最后一个参数中块的参数。

Map(coordinateRegion: $container.region, 
    annotationItems: container.annotationLocations) { 
        (location) -> MapPin in
            MapPin(coordinate: location.coordinate)
    })

路由怎么样?在SwiftUI中是否可以实现,还是目前不能呢? - M1X
1
我不知道。希望他们会发布关于新地图功能的视频,但看来我们还没有得到。我们将看到它是否在接下来的几个测试版中得到充实... - promacuser
你能用MapAnnotation举个例子吗?我需要显示一些文本,所以我需要MapAnnotation。 - M1X

1
应该像以下这样(由于提供的快照缺少依赖项,未经测试)。
Map(mapRect: .constant(mapRect), annotationItems: coll) { point in
   MapAnnotation(coordinate: point.coordinate) {
    Text(point.title ?? "")
   }
}

1
代码编译正常,但我看不到红色注释,有什么想法吗?我还在哪里做错了吗? - M1X
我还更新了我的问题,加入了硬编码坐标进行测试。 - M1X

0
对于任何正在寻找SwiftUI MKPolyline路线的人来说
    struct MapView: View {
        
        @ObservedObject var viewModel: MapViewModel
        
        var body: some View {
            VStack(spacing: 0) {
                Text("Status")
                    .padding()
                MapViewRepresentable(exampleRoute: viewModel.exampleRoute)
                Button("Button", action: { })
                    .padding()
            }
        }
        
    }
    
    
    struct MapView_Previews: PreviewProvider {
        static var previews: some View {
            MapView(viewModel: MapViewModel())
        }
    }
    
    
    struct MapViewRepresentable: UIViewRepresentable {
        
        private let initialRegion = CoordinateRegion.initial
        
        let exampleRoute: MKPolyline
        
        func makeCoordinator() -> Coordinator {
            return Coordinator(self)
        }
        
        func makeUIView(context: UIViewRepresentableContext<MapViewRepresentable>) -> MKMapView {
            let mapView = MKMapView()
            mapView.delegate = context.coordinator
            mapView.setRegion(initialRegion, animated: false)
            mapView.showsUserLocation = true
            mapView.addOverlay(exampleRoute)
            return mapView
        }
    
        func updateUIView(_ view: MKMapView,
                          context: UIViewRepresentableContext<MapViewRepresentable>) {
    
        }
        
        class Coordinator: NSObject, MKMapViewDelegate {
            let parent: MapViewRepresentable
            init(_ mapView: MapViewRepresentable) {
                parent = mapView
            }
            func mapView(_ mapView: MKMapView,
                         rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
                let polylineRenderer: MKPolylineRenderer = MKPolylineRenderer(overlay: overlay)
                polylineRenderer.lineWidth = 3
                polylineRenderer.strokeColor = UIColor.red
                return polylineRenderer
            }
        }
        
    }


class MapViewModel: ObservableObject {
    
    @Published private(set) var exampleRoute = createPolylines()
    
    static func createPolylines() -> MKPolyline {
        var coordinates1 = createExampleRoute()
        return MKPolyline(coordinates: &coordinates1, count: coordinates1.count)
    }
    
    static func createExampleRoute() -> [CLLocationCoordinate2D] {
        return [CLLocationCoordinate2D(latitude: 60.608905, longitude: 39.814428),
                CLLocationCoordinate2D(latitude: 60.609073, longitude: 39.812000),
                CLLocationCoordinate2D(latitude: 60.610429, longitude: 39.812071)]
    }
    
}


struct CoordinateRegion {
    static let initial = MKCoordinateRegion(center: CLLocationManager().location?.coordinate
                                                    ?? CLLocationCoordinate2D(latitude: 60.608905,
                                                                              longitude: 39.814428),
                                            span: MKCoordinateSpan(latitudeDelta: 0.05,
                                                                   longitudeDelta: 0.05))
    func getCurrentLocation() -> CLLocationCoordinate2D {
        return CLLocationManager().location!.coordinate
    }
    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接