{"id":18839736,"url":"https://github.com/maximbilan/ios-mapkit-tutorial","last_synced_at":"2025-04-14T07:03:41.603Z","repository":{"id":64060241,"uuid":"49275549","full_name":"maximbilan/iOS-MapKit-Tutorial","owner":"maximbilan","description":"iOS MapKit Getting Started","archived":false,"fork":false,"pushed_at":"2018-09-22T09:24:28.000Z","size":1932,"stargazers_count":26,"open_issues_count":0,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-14T07:02:00.713Z","etag":null,"topics":["ios","ios-mapkit","location","location-services","map","mapkit","mkmapview","swift","tutorial"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maximbilan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-08T14:09:30.000Z","updated_at":"2023-01-17T21:27:25.000Z","dependencies_parsed_at":"2022-12-02T10:54:21.611Z","dependency_job_id":null,"html_url":"https://github.com/maximbilan/iOS-MapKit-Tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximbilan%2FiOS-MapKit-Tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximbilan%2FiOS-MapKit-Tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximbilan%2FiOS-MapKit-Tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximbilan%2FiOS-MapKit-Tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maximbilan","download_url":"https://codeload.github.com/maximbilan/iOS-MapKit-Tutorial/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248837278,"owners_count":21169374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","ios-mapkit","location","location-services","map","mapkit","mkmapview","swift","tutorial"],"created_at":"2024-11-08T02:43:55.089Z","updated_at":"2025-04-14T07:03:40.638Z","avatar_url":"https://github.com/maximbilan.png","language":"Swift","readme":"# iOS MapKit Getting Started\n\nHi, I would like to tell how to work with \u003ci\u003eMapKit\u003c/i\u003e in iOS using \u003ci\u003eSwift\u003c/i\u003e. This post for beginners, I will try to tell as detailed as possible.\n\n![alt tag](https://raw.github.com/maximbilan/iOS-MapKit-Tutorial/master/images/1.png)\n\nApple provides \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/MapKit/Reference/MKMapView_Class/index.html#//apple_ref/occ/cl/MKMapView\"\u003eMKMapView\u003c/a\u003e\u003c/i\u003e class for working with map. This class displays maps and provides interface to navigate map content. Detailed documentation about this class you can found \u003ca href=\"https://developer.apple.com/library/mac/documentation/MapKit/Reference/MKMapView_Class/\"\u003ehere\u003c/a\u003e. Let's start.\n\nFirst of all add the \u003ci\u003emap view\u003c/i\u003e to your \u003ci\u003estoryboard\u003c/i\u003e or \u003ci\u003exib\u003c/i\u003e, or create from the code. In this sample I will create a simple \u003ci\u003estoryboard\u003c/i\u003e with one \u003ci\u003eUIViewController\u003c/i\u003e which will contain a \u003ci\u003emap view\u003c/i\u003e.\n\n![alt tag](https://raw.github.com/maximbilan/iOS-MapKit-Tutorial/master/images/2.png)\n\nThe second main part, you need to add \u003ci\u003eMapKit\u003c/i\u003e framework to your project.\n\n![alt tag](https://raw.github.com/maximbilan/iOS-MapKit-Tutorial/master/images/3.png)\n\nIf you see the map when you run the application, then you are on the right way.\n\n![alt tag](https://raw.github.com/maximbilan/iOS-MapKit-Tutorial/master/images/4.png)\n\nPlease add an outlet of map view object to your \u003ci\u003eUIViewController\u003c/i\u003e. Also you need to import \u003ci\u003eMapKit\u003c/i\u003e module in the \u003ci\u003eUIViewController\u003c/i\u003e.\n\n\u003cpre\u003e\nimport MapKit\n\u003c/pre\u003e\n\nApple provides \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/MapKit/Reference/MKMapViewDelegate_Protocol/\"\u003eMKMapViewDelegate\u003c/a\u003e\u003c/i\u003e and \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/\"\u003eCLLocationManagerDelegate\u003c/a\u003e\u003c/i\u003e delegates for developers. The \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/MapKit/Reference/MKMapViewDelegate_Protocol/\"\u003eMKMapViewDelegate\u003c/a\u003e\u003c/i\u003e protocol defines a set of optional methods that you can use to receive map-related update messages. Because many map operations require the \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/MapKit/Reference/MKMapView_Class/index.html#//apple_ref/occ/cl/MKMapView\"\u003eMKMapView\u003c/a\u003e\u003c/i\u003e class to load data asynchronously, the map view calls these methods to notify your application when specific operations complete. The map view also uses these methods to request annotation and overlay views and to manage interactions with those views. More details you can found \u003ca href=\"https://developer.apple.com/library/ios/documentation/MapKit/Reference/MKMapViewDelegate_Protocol/\"\u003ehere\u003c/a\u003e. The \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/\"\u003eCLLocationManagerDelegate\u003c/a\u003e\u003c/i\u003e protocol defines the methods used to receive location and heading updates from a \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/occ/cl/CLLocationManager\"\u003eCLLocationManager\u003c/a\u003e\u003c/i\u003e object. More details \u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/\"\u003ehere\u003c/a\u003e.\n\nDon’t forget set up a delegate in your code.\n\n\u003cpre\u003e\nimport MapKit\nclass ViewController: UIViewController, MKMapViewDelegate {\n  @IBOutlet weak var mapView: MKMapView!\n  override func viewDidLoad() {\n    super.viewDidLoad()\n    mapView.delegate = self\n  }\n}\n\u003c/pre\u003e\n\nOr via \u003ci\u003eInterface Builder\u003c/i\u003e.\n\n![alt tag](https://raw.github.com/maximbilan/iOS-MapKit-Tutorial/master/images/5.png)\n\nFor \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/\"\u003eCLLocationManagerDelegate\u003c/a\u003e\u003c/i\u003e the same:\n\n\u003cpre\u003e\nlocationManager.delegate = self\n\u003c/pre\u003e\n\nLet’s try to add a button for detecting the current location:\n\n\u003cpre\u003e\nlet currentLocationButton = UIBarButtonItem(title: \"Current Location\", style: UIBarButtonItemStyle.Plain, target: self, action: \"currentLocationButtonAction:\")\nself.navigationItem.leftBarButtonItem = currentLocationButton\n\u003c/pre\u003e\n\nThen implement \u003ci\u003ecurrentLocationButtonAction\u003c/i\u003e method:\n\n\u003cpre\u003e\nfunc currentLocationButtonAction(sender: UIBarButtonItem) {\n  if (CLLocationManager.locationServicesEnabled()) {\n    if locationManager == nil {\n      locationManager = CLLocationManager()\n    }\n    locationManager?.requestWhenInUseAuthorization()\n    locationManager.delegate = self\n    locationManager.desiredAccuracy = kCLLocationAccuracyBest\n    locationManager.requestAlwaysAuthorization()\n    locationManager.startUpdatingLocation()\n  }\n}\n\u003c/pre\u003e\n\nAfter that when you requested the location, you need to implement \u003ci\u003edidUpdateLocations\u003c/i\u003e from \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/\"\u003eCLLocationManagerDelegate\u003c/a\u003e\u003c/i\u003e, and here you can add a location to \u003ci\u003emapView\u003c/i\u003e. Please see the next code:\n\n\u003cpre\u003e\nfunc locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {\n  let location = locations.last\n  let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)\n  let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))\n  self.mapView.setRegion(region, animated: true)\n  if self.mapView.annotations.count != 0 {\n    annotation = self.mapView.annotations[0]\n    self.mapView.removeAnnotation(annotation)\n  }\n  let pointAnnotation = MKPointAnnotation()\n  pointAnnotation.coordinate = location!.coordinate\n  pointAnnotation.title = \"\"\n  mapView.addAnnotation(pointAnnotation)\n}\n\u003c/pre\u003e\n\n\u003cb\u003eImportant note:\u003c/b\u003e The current authorization status for location data is available from the \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/occ/clm/CLLocationManager/authorizationStatus\"\u003eauthorizationStatus\u003c/a\u003e\u003c/i\u003e class method of \u003ci\u003eCLLocationManager\u003c/i\u003e. In requesting authorization in iOS 8 and later, you must use the \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/occ/instm/CLLocationManager/requestWhenInUseAuthorization\"\u003erequestWhenInUseAuthorization\u003c/a\u003e\u003c/i\u003e or \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/occ/instm/CLLocationManager/requestAlwaysAuthorization\"\u003erequestAlwaysAuthorization\u003c/a\u003e\u003c/i\u003e method and include the \u003ci\u003eNSLocationWhenInUseUsageDescription\u003c/i\u003e or \u003ci\u003eNSLocationAlwaysUsageDescription\u003c/i\u003e key in your \u003cb\u003eInfo.plist\u003c/b\u003e file to indicate the level of authorization you require.\n\nLet’s continue…\n\n![alt tag](https://raw.github.com/maximbilan/iOS-MapKit-Tutorial/master/images/6.png)\n\nNow I will tell how to do a simple search.\n\nFirst of all you need to add \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/tvos/documentation/UIKit/Reference/UISearchBarDelegate_Protocol/index.html\"\u003eUISearchBarDelegate\u003c/a\u003e\u003c/i\u003e to your \u003ci\u003eUIViewController\u003c/i\u003e. The \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/tvos/documentation/UIKit/Reference/UISearchBarDelegate_Protocol/index.html\"\u003eUISearchBarDelegate\u003c/a\u003e\u003c/i\u003e protocol defines the optional methods you implement to make a \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/tvos/documentation/UIKit/Reference/UISearchBar_Class/index.html#//apple_ref/occ/cl/UISearchBar\"\u003eUISearchBar\u003c/a\u003e\u003c/i\u003e control functional. A \u003ci\u003e\u003ca href=\"https://developer.apple.com/library/tvos/documentation/UIKit/Reference/UISearchBar_Class/index.html#//apple_ref/occ/cl/UISearchBar\"\u003eUISearchBar\u003c/a\u003e\u003c/i\u003e object provides the user interface for a search field on a bar, but it’s the application’s responsibility to implement the actions when buttons are tapped. At a minimum, the delegate needs to perform the actual search when text is entered in the text field.\n\nPlease add the following variables to your class:\n\n\u003cpre\u003e\nprivate var searchController: UISearchController!\nprivate var localSearchRequest: MKLocalSearchRequest!\nprivate var localSearch: MKLocalSearch!\nprivate var localSearchResponse: MKLocalSearchResponse!\n\u003c/pre\u003e\n\nAnd then we add a search navigation bar button:\n\n\u003cpre\u003e\nlet searchButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Search, target: self, action: \"searchButtonAction:\")\nself.navigationItem.rightBarButtonItem = searchButton\n\u003c/pre\u003e\n\n![alt tag](https://raw.github.com/maximbilan/iOS-MapKit-Tutorial/master/images/7.png)\n\nImplementation of the search button action:\n\n\u003cpre\u003e\nfunc searchButtonAction(button: UIBarButtonItem) {\n  if searchController == nil {\n    searchController = UISearchController(searchResultsController: nil)\n  }\n  searchController.hidesNavigationBarDuringPresentation = false\n  self.searchController.searchBar.delegate = self\n  presentViewController(searchController, animated: true, completion: nil)\n}\n\u003c/pre\u003e\n\nAnd the last point, we need to implement \u003ci\u003esearchBarSearchButtonClicked\u003c/i\u003e method from \u003ci\u003eUISearchBarDelegate\u003c/i\u003e:\n\n\u003cpre\u003e\nfunc searchBarSearchButtonClicked(searchBar: UISearchBar) {\n  searchBar.resignFirstResponder()\n  dismissViewControllerAnimated(true, completion: nil)\n  \n  if self.mapView.annotations.count != 0 {\n    annotation = self.mapView.annotations[0]\n    self.mapView.removeAnnotation(annotation)\n  }\n  localSearchRequest = MKLocalSearchRequest()\n  localSearchRequest.naturalLanguageQuery = searchBar.text\n  localSearch = MKLocalSearch(request: localSearchRequest)\n  localSearch.startWithCompletionHandler { [weak self]  (localSearchResponse, error) -\u003e Void in\n    if localSearchResponse == nil {\n      let alert = UIAlertView(title: nil, message: “Place not found”, delegate: self, cancelButtonTitle: “Try again”)\n      alert.show()\n      return\n    }\n    let pointAnnotation = MKPointAnnotation()\n    pointAnnotation.title = searchBar.text\n    pointAnnotation.coordinate = CLLocationCoordinate2D(latitude:     localSearchResponse!.boundingRegion.center.latitude, longitude: localSearchResponse!.boundingRegion.center.longitude)\n    let pinAnnotationView = MKPinAnnotationView(annotation: pointAnnotation, reuseIdentifier: nil)\n    self!.mapView.centerCoordinate = pointAnnotation.coordinate\n    self!.mapView.addAnnotation(pinAnnotationView.annotation!)\n  }\n}\n\u003c/pre\u003e\n\nThe code is simple and I think you will figure out very easily. One small thing which I would like to share, it is a map type. \u003ci\u003eMapView\u003c/i\u003e object has \u003ci\u003emapType\u003c/i\u003e property with next values, which you can easily set up:\n\n\u003cpre\u003e\nStandard\nSatellite\nHybrid\n\u003c/pre\u003e\n\n![alt tag](https://raw.github.com/maximbilan/iOS-MapKit-Tutorial/master/images/8.png)\n\nThat’s all, I hope these tutorials help you to start developing apps using \u003ci\u003eMapKit\u003c/i\u003e.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximbilan%2Fios-mapkit-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaximbilan%2Fios-mapkit-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximbilan%2Fios-mapkit-tutorial/lists"}