MapKit in SwiftUI
How to use MKMapViewDelegate methods with SwiftUI?
Most of the iOS developers know SwiftUI is similar to the UIKit but still, there are some differences in the development phase. To learn more, let’s create MKMapView
inside SwiftUI.
Let’s start with it.
If you are new with the SwiftUI then you need to check my previous blog for getting started with the SwiftUI. Now coming to the point. Create your new class with the SwiftUI.
Go to > XCode > File > New > File > SwiftUI View > Next > Name for the File
- Now open your file -
import SwiftUIstruct MapView: View {
var body: some View {
Text("Hello World!")
}
}
In this class, we don’t require View
protocol in place we are going to use UIViewRepresentable
protocol for UIKit support inside the SwiftUI because we don’t have MapKit.
Now the question about what is the UIViewRepresentable
why not View
?
Press ⌘ + Click
After looking into we are getting the summary -“A view that represents a UIKit view.”
After replacing View
Protocol with UIViewRepresentable
The protocol we have to remove a body from your MapView
class.
var body: some View {
Text("Hello World!")
}
You will get the warning ⚠️ for the confirm UIViewRepresentable
protocol.
import SwiftUI
import MapKitstruct MapView: UIViewRepresentable {
/**
- Description - Replace the body with a make UIView(context:) method that creates and return an empty MKMapView
*/
func makeUIView(context: Context) -> MKMapView{
MKMapView(frame: .zero)
}
}
Adding one more function inside MapView class for the updates presented view
func updateUIView(_ view: MKMapView, context: Context){
let coordinate = CLLocationCoordinate2D(
latitude: 12.9716, longitude: 77.5946)
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
Adding the Pinpoint (Annotation) now inside the Map.
Creating now MKAnnotation
model -
class LandmarkAnnotation: NSObject, MKAnnotation {
let title: String?
let subtitle: String?
let coordinate: CLLocationCoordinate2Dinit(title: String?,
subtitle: String?,
coordinate: CLLocationCoordinate2D) {
self.title = title
self.subtitle = subtitle
self.coordinate = coordinate
}
}
Adding inside our MapView class-
struct MapView: UIViewRepresentable {
//Model with test data
let landmarks = LandmarkAnnotation.requestMockData()
/**
- Description - Replace the body with a make UIView(context:) method that creates and return an empty MKMapView
*/
func makeUIView(context: Context) -> MKMapView{
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context){
//If you changing the Map Annotation then you have to remove old Annotations
//mapView.removeAnnotations(mapView.annotations)
//passing model array here
view.addAnnotations(landmarks)
}
}
Now changing the image for the MKAnnotation.
Accessing the Protocol delegate methods inside the SwiftUI
required Coordinator
. You can write it inside your class or out of the class.
class MapViewCoordinator: NSObject, MKMapViewDelegate {
var mapViewController: MapView
init(_ control: MapView) {
self.mapViewController = control
}
func mapView(_ mapView: MKMapView, viewFor
annotation: MKAnnotation) -> MKAnnotationView?{
//Custom View for Annotation
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "customView")
annotationView.canShowCallout = true
//Your custom image icon
annotationView.image = UIImage(named: "locationPin")
return annotationView
}
}
Adding this Coordinator
inside MapView
class.
func makeCoordinator() -> MapViewCoordinator{
MapViewCoordinator(self)
}
Once more change required for the delegate -
func updateUIView(_ view: MKMapView, context: Context){
//If you changing the Map Annotation then you have to remove old Annotations
//mapView.removeAnnotations(mapView.annotations)
//assigning delegate
view.delegate = context.coordinator
//passing model array here
view.addAnnotations(landmarks)
}
Final output of this code-
You can add any kind of image as an annotation and after clicking on this you will see the Title and subtitle inside the custom view.
Conclusion
In this part, you came to know how to create an intermediate map view to custom. This is a pretty interesting 🧐 building MapView
with the SwiftUI
. It’s completely programmatically layout design. Just in few lines of code, you can make decent Design.
UIViewRepresentable
the protocol is a very important part of this article you came to know now how to add UIKit
inside the SwiftUI
.
Coordinator
was the key 🔑 point inside the for adding Delegates methods inside your class and you can give any name to this just like a normal class with the Protocols
whose methods you wanted to confirm inside your class.
This is a basic example of the MapKit
inside the SwiftUI
you can add inside your applications view with custom height and width. I have not removed pinpoints from the map view but I have added the code inside the example if you wanted to remove it you can clean older and add new. It was the hardcoded data so not required for me but in realtime applications, It’s required. You can add UIKit
the inside SwiftUI
with the help of UIViewRepresentable
protocol. I hope you like it. 😊✌🏼
Checkout Github repo for the final code here. 🚀
Framework Integration Interfacing with UIKit.
Source- Apple SwiftUI tutorial
Thanks for reading 🙌🏼
If you having any queries regarding this tutorial? | If you think you can do more simple way or little bit more extra things with this stuff please let me know questions, feedback or comments -on Twitter