I decided to switch from wrapping MKMapView into a UIViewRepresentable to the new Map()
in SwiftUI.
I was able to display correctly a MKMapRect
into the Map()
but I am unable to display two MKPointAnnotation
there. Also my route between these annotation is not showing
It is requiring me to provide an RandomAccessCollection
and a (Identifiable) -> MapAnnotationProtocol>
but I do not know what to put there.
Any idea what should I put in (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)
}
}
You don't need to do MKPointAnnotation
anymore. Currently, in Xcode 12.0 Beta, there are three structs that SwiftUI provides to satisfy the MapAnnotationProtocol
:
MapAnnotation
MapMarker
MapPin
The RandomAccessCollection
should be any collection (an array will do) of objects that adopt Identifiable
. These used as the argument of the block in the final argument of the Map
initializer.
Map(coordinateRegion: $container.region,
annotationItems: container.annotationLocations) {
(location) -> MapPin in
MapPin(coordinate: location.coordinate)
})
It seems to me that MapAnnotation
requires you to implement the whole view that will be rendered on the map, so if you want both the red pin and some text, you will have to create that pin yourself (e.g. as an instance of Image with SF Symbol). Of course it doesn't look as good as the pin from MapMarker
but at least it's a start.
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)
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With