Search code examples
iosswiftgeolocationmapkitcore-location

Getting longitude and latitude


I have experience crash of the app when using it in US. In all other countries same code is working. The crash is happening on line:

let latitude = String(format: "%.7f", currentLocation.coordinate.latitude)

I really can't see what is the problem, specially cos is related to US and not to other counties. Any help will be very very much appreciate.

My UserLocation.swift looks like this:

import UIKit
import MapKit

public class GPSLocation {

static let sharedInstance = GPSLocation()

//MARK: Public variables

public var intermediateLatitude: String?
public var intermediateLongitude: String?
public var intermediateCountry: String?
public var intermediateCity: String?
public var intermediateTimeZone: String?

//MARK: Get Longitude, Country Code and City name

func getGPSLocation(completition: @escaping () -> Void) {

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

        let locManager = manager
        var currentLocation: CLLocation!
        locManager.desiredAccuracy = kCLLocationAccuracyBest

        if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse || CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) {

            currentLocation = locManager.location

            if currentLocation != nil {
                // Get longitude & latitude
                let latitude = String(format: "%.7f", currentLocation.coordinate.latitude)
                let longitude = String(format: "%.7f", currentLocation.coordinate.longitude)
                self.intermediateLatitude = latitude
                self.intermediateLongitude = longitude
                // debugPrint("Latitude:",latitude)
                // debugPrint("Longitude:",longitude)

                // Get local time zone GMT
                let localTimeZoneAbbreviation = TimeZone.current.abbreviation() ?? ""  // "GMT-2"
                let indexStartOfText = localTimeZoneAbbreviation.index(localTimeZoneAbbreviation.startIndex, offsetBy: 3) // 3
                let timeZone = localTimeZoneAbbreviation.substring(from: indexStartOfText) // "-2"
                self.intermediateTimeZone = timeZone
                // debugPrint("GMT:",timeZone)

                // Get Country code and City
                let location = CLLocation(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude)
                fetchCountryAndCity(location: location) { countryCode, city in
                    self.intermediateCountry = countryCode
                    self.intermediateCity = city
                    // debugPrint("Country code:",countryCode)
                    // debugPrint("City:",city)

                    completition()
                }
            } else {
                // Location is NIL
            }
        }
    }
    locManager.delegate = self // and conform protocol
    locationManager.startUpdatingLocation()
}

//MARK: Find countryCode & City name from longitude & latitude

func fetchCountryAndCity(location: CLLocation, completion: @escaping (String, String) -> ()) {
    CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
        if let error = error {
            debugPrint(error)
        } else if let countryCode = placemarks?.first?.isoCountryCode,
            let city = placemarks?.first?.locality {
            completion(countryCode, city)
        }
    }
}
}

Solution

  • You need to check location in delegate method

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
              manager.stopUpdatingLocation() // if you dont want continuously update
    
                currentLocation = manager.location
             let location = CLLocation(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude)
        fetchCountryAndCity(location: location) { countryCode, city in
            self.intermediateCountry = countryCode
            self.intermediateCity = city
            // debugPrint("Country code:",countryCode)
            // debugPrint("City:",city)
    
            completition()
        }
       }
    

    And set delegate

    locManager.delegate = self // and conform protocol 
    locationManager.startUpdatingLocation()