-
Notifications
You must be signed in to change notification settings - Fork 472
Maps
This guide is an introduction to using MapKit to set up a map view, plot locations, and draw overlays on it in your app.
Drag a Map Kit View from the Object Library onto your storyboard:
Add MapKit framework to your view controller:
import MapKit
Create an outlet:
Control-drag the map view in the storyboard inside your view controller definition.
Release and name the outlet: mapView
You should now see a map when you build and run your project!
You probably want to see a particular area of the world in your app rather than the entire world. So let’s set up so initial properties of the map.
For example, let’s center the map in San Francisco (37.7833, -122.4167). There are two things you need to center the map at a location:
- The coordinates
- A region to display to get the correct zoom level of the map. Create a MKCoordinateSpan that defines the area spanned by the region you want to display. One degree of latitude is approximately 111 km or 69 miles.
override func viewDidLoad() {
super.viewDidLoad()
// set the region to display, this also sets a correct zoom level
// set starting center location in San Francisco
let centerLocation = CLLocation(latitude: 37.7833, longitude: -122.4167)
goToLocation(centerLocation)
}
func goToLocation(location: CLLocation) {
let span = MKCoordinateSpanMake(0.1, 0.1)
let region = MKCoordinateRegionMake(location.coordinate, span)
mapView.setRegion(region, animated: false)
}
Build and run your app again. You should see your map centered in San Francisco (or your desired location).
MKMapView already supports standard interactions like scrolling to a different part of the map and adjusting the zoom level. These interactions are enabled by default, but you can disable them by accessing the properties in the map view: zoomEnabled, scrollEnabled, pitchEnabled, rotateEnabled
You can also center the map at the user's current location. First, request permission to use the user's location:
Import CoreLocation framework
import CoreLocation
Add a locationManager:
class MapViewController: UIViewController, CLLocationManagerDelegate {
@IBOutlet weak var mapView: MKMapView!
var locationManager : CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
...
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.distanceFilter = 200
locationManager.requestWhenInUseAuthorization()
}
}
Edit the Info.plist to tell users why we're requesting their location:
Click on Info.plist and add a new row with key: NSLocationWhenInUseUsageDescription and value: To show your location on the map
To show the user's location on the map:
Click on your map view and then check Shows User Location in the Attributes Inspector
Go to the user's location when permission has been given:
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.authorizedWhenInUse {
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
let span = MKCoordinateSpanMake(0.1, 0.1)
let region = MKCoordinateRegionMake(location.coordinate, span)
mapView.setRegion(region, animated: false)
}
}
In the simulator, select Debug > Location
Location with Apple selected
MKAnnotation is used for annotations in a map. It contains the coordinate of the annotation only. A MKAnnotationView is used to display an annotation. We'll go over different ways to display an annotation:
MKPointAnnotation is a simple annotation and supports a title.
// add an Annotation with a coordinate: CLLocationCoordinate2D
func addAnnotationAtCoordinate(coordinate: CLLocationCoordinate2D) {
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = "An annotation!"
mapView.addAnnotation(annotation)
}
// add an annotation with an address: String
func addAnnotationAtAddress(address: String, title: String) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
if let placemarks = placemarks {
if placemarks.count != 0 {
let coordinate = placemarks.first!.location!
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate.coordinate
annotation.title = title
self.mapView.addAnnotation(annotation)
}
}
}
}
MKAnnotationView is used to create an annotation with a custom image. We'll need MKMapViewDelegate
class MapViewController: UIViewController, MKMapViewDelegate {
...
}
Also implement the following in the view controller:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "customAnnotationView"
// custom image annotation
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if (annotationView == nil) {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "customAnnotationImage")
return annotationView
}
MKPinAnnotationView is a subclass of MKAnnotationView. It uses the pin graphic as the annotation image, and you can set the pin color and drop animation.
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "customAnnotationView"
// custom pin annotation
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView
if (annotationView == nil) {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
}
else {
annotationView!.annotation = annotation
}
annotationView!.pinTintColor = UIColor.greenColor()
return annotationView
}
Here's an example of a circular overlay centered at a coordinate.
override func viewDidLoad() {
super.viewDidLoad()
...
mapView.delegate = self
// draw circular overlay centered in San Francisco
let coordinate = CLLocationCoordinate2D(latitude: 37.7833, longitude: -122.4167)
let circleOverlay: MKCircle = MKCircle(centerCoordinate: coordinate, radius: 1000)
mapView.addOverlay(circleOverlay)
}
Implement the following in the view controller:
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
let circleView = MKCircleRenderer(overlay: overlay)
circleView.strokeColor = UIColor.redColor()
circleView.lineWidth = 1
return circleView
}
In addition to MapKit, you can integrate other map SDKs in your app. One reason to use alternate maps is for cross platform consistency.
- Google Maps SDK for iOS
- The Google Places SDK is also packaged in Google Maps SDK, useful for autocomplete searching.
- Mapbox iOS SDK
- Mapbox is a set of open source tools used to create custom maps.
- OpenStreetMap API
- OpenStreetMap is a project that creates and distributes data of the world.
- OpenStreetMap API allows reading and editing raw data, and does not provide a way to embed a map (like in MapKit or Google Maps).
- OpenStreetMap has a lot of map features like buildings, highways, shops...