Show Current Location and Update Location in MKMapView in Swift
Asked Answered
C

11

51

I am learning how to use the new Swift language (only Swift, no Objective-C). To do it, I want to do a simple view with a map (MKMapView). I want to find and update the location of the user (like in the Apple Map app).

I tried this, but nothing happened:

import MapKit
import CoreLocation

class MapView : UIViewController, CLLocationManagerDelegate {

    @IBOutlet weak var map: MKMapView!
    var locationManager: CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()

        if (CLLocationManager.locationServicesEnabled())
        {
            locationManager = CLLocationManager()
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.requestAlwaysAuthorization()
            locationManager.startUpdatingLocation()
        }
    }
}

Could you please help me?

Cowen answered 22/8, 2014 at 14:31 Comment(1)
Simple go through this link: #25449969Bautram
E
81

You have to override CLLocationManager.didUpdateLocations (part of CLLocationManagerDelegate) to get notified when the location manager retrieves the current location:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let location = locations.last{
        let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
        self.map.setRegion(region, animated: true)
    }
}

NOTE: If your target is iOS 8 or above, you must include the NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in your Info.plist to get the location services to work.

Equities answered 22/8, 2014 at 16:27 Comment(9)
Thanks for your answer Zisoft. But, to use the function, I have to "save" all my new locations in a kind of list ? Then, is startUpdatingLocation() suffisant to update the location ? NOTE: Euh... sorry but how can I do it please ? :s Thank you very much !Cowen
After you have called startUpdatingLocation once, didUpdateLocations is fired everytime a location change is detected. You can do whatever you need with the location, i.e. store it in an array to draw a path on the map view.Equities
ok thanks. And how can I include the NSLocationAlwaysUsageDescription key in my Info.plist please ?Cowen
In XCode, click on Info.plist and add a new row. Use NSLocationAlwaysUsageDescription as the key and the text you want to present to the user as value (String).Equities
The value should be a string. This text is displayed by the system when it asks the user for permission to use the location services. This is mandatory in iOS 8.Equities
Just a comment to the answer : We can not use .lastfor an array, so I used array[count-1]Cowen
You can use array.last as of XCode 6 Beta 5.Equities
I'd recommend using NSLocationWhenInUseUsageDescription if you only need to track the user's location when the app is running. People are more likely to click "Accept" that wayCromlech
Do you know how to do it with GoogleMaps? Because self.map.setRegion(region, animated: true) can't work in a GoogleMaps mapViewAustronesia
B
39

100% working, easy steps and tested

Import libraries:

import MapKit
import CoreLocation

set delegates:

CLLocationManagerDelegate,MKMapViewDelegate

Take variable:

let locationManager = CLLocationManager()

write this code on viewDidLoad():

self.locationManager.requestAlwaysAuthorization()

    // For use in foreground
    self.locationManager.requestWhenInUseAuthorization()

    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.startUpdatingLocation()
    }

    mapView.delegate = self
    mapView.mapType = .standard
    mapView.isZoomEnabled = true
    mapView.isScrollEnabled = true

    if let coor = mapView.userLocation.location?.coordinate{
        mapView.setCenter(coor, animated: true)
    }

Write delegate method for location:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate

    mapView.mapType = MKMapType.standard

    let span = MKCoordinateSpanMake(0.05, 0.05)
    let region = MKCoordinateRegion(center: locValue, span: span)
    mapView.setRegion(region, animated: true)

    let annotation = MKPointAnnotation()
    annotation.coordinate = locValue
    annotation.title = "Javed Multani"
    annotation.subtitle = "current location"
    mapView.addAnnotation(annotation)

    //centerMap(locValue)
}

Do not forgot to set permission in info.plist

<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>

It's look like:

enter image description here

Bautram answered 9/3, 2018 at 10:11 Comment(0)
O
21

For swift 3 and XCode 8 I find this answer:

  • First, you need set privacy into info.plist. Insert string NSLocationWhenInUseUsageDescription with your description why you want get user location. For example, set string "For map in application".

  • Second, use this code example

    @IBOutlet weak var mapView: MKMapView!
    
    private var locationManager: CLLocationManager!
    private var currentLocation: CLLocation?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        mapView.delegate = self
    
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
    
        // Check for Location Services
    
        if CLLocationManager.locationServicesEnabled() {
            locationManager.requestWhenInUseAuthorization()
            locationManager.startUpdatingLocation()
        }
    }
    
    // MARK - CLLocationManagerDelegate
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        defer { currentLocation = locations.last }
    
        if currentLocation == nil {
            // Zoom to user location
            if let userLocation = locations.last {
                let viewRegion = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 2000, 2000)
                mapView.setRegion(viewRegion, animated: false)
            }
        }
    }
    
  • Third, set User Location flag in storyboard for mapView.

Outfall answered 27/4, 2017 at 13:16 Comment(0)
H
7

MyLocation is a Swift iOS Demo.

You can use this demo for the following:

  1. Show the current location.

  2. Choose other location: in this case stop tracking the location.

  3. Add a push pin to a MKMapView(iOS) when touching.

Heeheebiejeebies answered 9/6, 2016 at 12:16 Comment(2)
Please don't add the same answer to multiple questions. Answer the best one and flag the rest as duplicates. See Is it acceptable to add a duplicate answer to several questions?Galvanometer
Thanks, I will do thatHeeheebiejeebies
S
5

Hi Sometimes setting the showsUserLocation in code doesn't work for some weird reason.

So try a combination of the following.

In viewDidLoad()

  self.mapView.showsUserLocation = true

Go to your storyboard in Xcode, on the right panel's attribute inspector tick the User location check box, like in the attached image. run your app and you should be able to see the User location

enter image description here

Solipsism answered 9/7, 2019 at 8:56 Comment(1)
Thanks, checkbox "User location" was exactly what I was looking for - blue point of current location.Acis
A
5

Swift 5.1

Get Current Location and Set on MKMapView

Import libraries:

import MapKit
import CoreLocation

set delegates:

CLLocationManagerDelegate , MKMapViewDelegate

Declare variable:

let locationManager = CLLocationManager()

Write this code on viewDidLoad():

self.locationManager.requestAlwaysAuthorization()
self.locationManager.requestWhenInUseAuthorization()

if CLLocationManager.locationServicesEnabled() {
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.startUpdatingLocation()
}
mapView.delegate = self
mapView.mapType = .standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true

if let coor = mapView.userLocation.location?.coordinate{
    mapView.setCenter(coor, animated: true)
}

Write delegate method for location:

func locationManager(_ manager: CLLocationManager, didUpdateLocations 
    locations: [CLLocation]) {
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate

    mapView.mapType = MKMapType.standard

    let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
    let region = MKCoordinateRegion(center: locValue, span: span)
    mapView.setRegion(region, animated: true)

    let annotation = MKPointAnnotation()
    annotation.coordinate = locValue
    annotation.title = "You are Here"
    mapView.addAnnotation(annotation)
}

Set permission in info.plist *

<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>
Antineutrino answered 30/7, 2020 at 9:43 Comment(0)
H
3

For Swift 2, you should change it to the following:

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let location = locations.last

    let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
    let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))

    self.map.setRegion(region, animated: true)
}
Hag answered 16/3, 2016 at 21:14 Comment(0)
A
3

You just need to set the userTrackingMode of the MKMapView. If you only want to display and track the user location and implement the same behaviour as the Apple Maps app uses, there is no reason for writing additional code.

mapView.userTrackingMode = .follow

See more at https://developer.apple.com/documentation/mapkit/mkmapview/1616208-usertrackingmode .

Ampereturn answered 31/1, 2020 at 10:29 Comment(0)
N
1

you have to override CLLocationManager.didUpdateLocations

 func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    let userLocation:CLLocation = locations[0] as CLLocation
    locationManager.stopUpdatingLocation()

    let location = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)

    let span = MKCoordinateSpanMake(0.5, 0.5)

    let region = MKCoordinateRegion (center:  location,span: span)

    mapView.setRegion(region, animated: true)
}

you also have to add NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription to your plist setting Result as value

Nasty answered 23/7, 2016 at 18:46 Comment(0)
C
1

In Swift 4, I had used the locationManager delegate function as defined above ..

func locationManager(manager: CLLocationManager!, 
    didUpdateLocations locations: [AnyObject]!) {

.. but this needed to be changed to ..

func locationManager(_ manager: CLLocationManager,
    didUpdateLocations locations: [CLLocation]) {

This came from .. https://github.com/lotfyahmed/MyLocation/blob/master/MyLocation/ViewController.swift - thanks!

Ceballos answered 27/12, 2017 at 23:49 Comment(0)
E
1
mapView.showsUserLocation = true

Create UIButton and add this action

@IBAction func showCurrentLocation(_ sender: Any) {
        let coordinate = mapView.userLocation.coordinate
        let center = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
        self.mapView.setRegion(region, animated: true)
    }
Equality answered 10/6, 2021 at 10:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.