user23509100
user23509100

Reputation:

Unable to show user current location in uikit

I am trying to display user current location when user granted to access user current location and also drop pin into current location of the user. I am using Xcode 15.3 and Swift version 5.10 . I have added the require filed into info.plit and define necessary function for it with outlet as well. But the problem is I got following warning into console ..

This method can cause UI unresponsiveness if invoked on the main thread. Instead, consider waiting for the -locationManagerDidChangeAuthorization: callback and checking authorizationStatus first.

This is error message into console and showing just Uk map into app when I run the app but I am expecting to show user current location with pin.

Error Domain=kCLErrorDomain Code=1 "(null)"

Here is the screenshot for info.plit ..

info.plit

Here is the screenshot when I run the app..

app screenshot

Here is the code ..

import UIKit
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate {

    @IBOutlet weak var myMap: MKMapView!
    
    let locationManager = CLLocationManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        
        if (CLLocationManager.locationServicesEnabled()) {
            
            locationManager.requestLocation()
            locationManager.startUpdatingLocation()
       }
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        if let userLocation = locations.first {
            manager.stopUpdatingLocation()
            
        let coordinate = CLLocationCoordinate2D(latitude: locationManager.location?.coordinate.latitude ?? 0.0, longitude: locationManager.location?.coordinate.longitude ?? 0.0)
            
        let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
        let region = MKCoordinateRegion(center: coordinate, span: span)
        myMap.setRegion(region, animated: true)
        let myPin = MKPointAnnotation()
        myPin.coordinate = coordinate
        myPin.title = "Hey There"
        myPin.subtitle = "I am here"
        myMap.addAnnotation(myPin)
            
        }
    }
  
   
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        
        switch manager.authorizationStatus {
        case .authorizedAlways:
            return
        case .authorizedWhenInUse:
            return
        case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
        case .restricted:
            locationManager.requestWhenInUseAuthorization()
        case .denied:
            return
        @unknown default:
            locationManager.requestWhenInUseAuthorization()
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error) {
        print(error)
    }
}

Upvotes: 1

Views: 109

Answers (1)

sonle
sonle

Reputation: 8866

Make sure providing both NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription keys in Info plist file.

In viewDidLoad, you're able to fetch the current authorizationStatus by:

switch locationManager.authorizationStatus {
case .notDetermined:
    //Request the first time
    locationManager.requestAlwaysAuthorization()
case .denied, .restricted:
    //TODO: Handle when user denied location permission
    //Force to open location permission in Setting for example
    break
default:
    break
}

Then didChangeAuthorization will trigger startUpdatingLocation because from now on, it's ready to work.

func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
    if manager.authorizationStatus == .authorizedWhenInUse || manager.authorizationStatus == .authorizedAlways {
        locationManager.startUpdatingLocation()
    }
}

You can keep stopUpdatingLocation whenever the current location is focused like above depend on the requirement, or put it on deinit/viewDidDisappear.

Upvotes: 0

Related Questions