skip to Main Content

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

2

Answers


  1. 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)
     }
    }
    
    Login or Signup to reply.
  2. I think you haven't added location permission description in your info.plist. That why xcode showing you => Error: This method can cause UI unresponsiveness if invoked on the main thread.
    
    In your info.plist file add this:
    
    <key>NSLocationUsageDescription</key>
    <string></string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string></string>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search