Search code examples
iosswiftcore-location

Swift MapKit Unable to show location with Pin


I am new to swift . I am trying to show user location with Pin . I added the permission in Info Plist to allow the user access . I am using the storyboard and I tried to edit the schema also added the default location but it did not fixed the problem . I am using CLLocationManagerDelegate with MapKit.

Here is my code for view controller ..

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    @IBOutlet var mapView: MKMapView!

    let manager  = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

    }
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.delegate = self
        manager.requestWhenInUseAuthorization()
        manager.stopUpdatingLocation()
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let location = locations.first {
            manager.stopUpdatingLocation()

            render(location)
        }
    }
    func  render(_ location: CLLocation) {

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

        let span  = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)

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

        mapView.setRegion(region, animated: true)

        let pin = MKPointAnnotation()
        pin.coordinate = coordinate
        mapView.addAnnotation(pin)

    }

}

Here is the screenshot of Info Plist Info Plist

Here is the screenshot shot when I run the app.. result

Here is the code warning .. Need to run into main thread


Solution

  • Try this way: conform your ViewController class to CLLocationManagerDelegate and MKMapViewDelegate, declare your objects:

    let mapView = MKMapView()
    let manager = CLLocationManager()
    

    in viewDidLoad present mapView and add constraints:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        mapView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(mapView)
        mapView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    
    }
    

    in viewDidAppear call requestAlwaysAuthorization and requestWhenInUseAuthorization and map configuration

    manager.requestAlwaysAuthorization()
    manager.requestWhenInUseAuthorization()
    
        if CLLocationManager.locationServicesEnabled() {
            manager.delegate = self
            manager.desiredAccuracy = kCLLocationAccuracyBest
            manager.startUpdatingLocation()
        }
        mapView.delegate = self
        mapView.mapType = .standard
        mapView.isZoomEnabled = true
        mapView.isScrollEnabled = true
        mapView.showsUserLocation = false // if you want to show default pin set to true
    
        if let coor = mapView.userLocation.location?.coordinate{
            mapView.setCenter(coor, animated: true)
        }
    

    After that set didUpdateLocations

    func locationManager(_ manager: CLLocationManager, didUpdateLocations
        locations: [CLLocation]) {
        
        guard let mylocation = manager.location else { return }
        
        let myCoordinates: CLLocationCoordinate2D = mylocation.coordinate
    
        mapView.mapType = MKMapType.standard
    
        let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
        let region = MKCoordinateRegion(center: myCoordinates, span: span)
        mapView.setRegion(region, animated: true)
        // comment pin object if showsUserLocation = true
        let pin = MKPointAnnotation()
        pin.coordinate = myCoordinates
        pin.title = "You are here"
        mapView.addAnnotation(pin)
    }
    

    my info.plist Privacy authorizations

    enter image description here

    The result, I set Tokyo on my simulator options scheme

    enter image description here

    enter image description here

    intere code with your DispatchQueue request in comments below:

    import UIKit
    import MapKit
    import CoreLocation
    
    class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
    
    let mapView = MKMapView()
    let manager = CLLocationManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        mapView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(mapView)
        mapView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        manager.requestAlwaysAuthorization()
        manager.requestWhenInUseAuthorization()
    
        if CLLocationManager.locationServicesEnabled() {
            DispatchQueue.main.async {
                self.manager.delegate = self
                self.manager.desiredAccuracy = kCLLocationAccuracyBest
                self.manager.startUpdatingLocation()
                self.mapView.delegate = self
                self.mapView.mapType = .standard
                self.mapView.isZoomEnabled = true
                self.mapView.isScrollEnabled = true
                self.mapView.showsUserLocation = false // if you want to show default pin
            }
        }
    
        if let coor = mapView.userLocation.location?.coordinate {
            mapView.setCenter(coor, animated: true)
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations
        locations: [CLLocation]) {
        
        guard let mylocation = manager.location else { return }
        
        let myCoordinates: CLLocationCoordinate2D = mylocation.coordinate
    
        mapView.mapType = MKMapType.standard
    
        let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
        let region = MKCoordinateRegion(center: myCoordinates, span: span)
        mapView.setRegion(region, animated: true)
        
        let pin = MKPointAnnotation()
        pin.coordinate = myCoordinates
        pin.title = "You are here"
        mapView.addAnnotation(pin)
     }
    }