2

I am having a strange error and cannot figure this one out. I have made a simple weather application that updates the weather based on the users coordinates. On simulator everything runs perfect however on device I get the error seen below.

Imgur

I declared my location manager in the class scope right above viewDidLoad:

let locationManager = CLLocationManager()

My viewDidLoad():

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startMonitoringSignificantLocationChanges()

        tableView.delegate = self
        tableView.dataSource = self

        currentWeather = CurrentWeather()
}

I am calling this function once the viewDidAppear:

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        locationAuthStatus()
    }


func locationAuthStatus() {
    if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
        currentLocation = locationManager.location
        Location.sharedInstance.latitude = currentLocation.coordinate.latitude
        Location.sharedInstance.longitude = currentLocation.coordinate.longitude
        currentWeather.downloadWeatherDetails {
            self.downloadForecastData {
                self.updateMainUI()
            }
        }
    } else {
        locationManager.requestWhenInUseAuthorization()
        locationAuthStatus()
    }
}

The error is the first line in the else statement above if the user hasn't been granted authorization yet. If you rerun the app after the crash, the weather will update just fine. Any help would be appreciated. Thank you.

UPDATE

Thanks to a suggestion in the comments I was able to fix my error. I moved the code from locationAuthStatus into the locationManager(_ manager: CLLocationManager, didChangeAuthorization.

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
        currentLocation = locationManager.location
        Location.sharedInstance.latitude = currentLocation.coordinate.latitude
        Location.sharedInstance.longitude = currentLocation.coordinate.longitude
        currentWeather.downloadWeatherDetails {
            self.downloadForecastData {
                self.updateMainUI()
            }
        }
    } else {
        locationManager.requestWhenInUseAuthorization()
    }
}

Thank you everyone for your help.

iNick
  • 105
  • 1
  • 11
  • Can I ask where did you call `locationAuthStatus()`? and where did you initialize the `locationManager`? – Ryan Wu Jan 26 '17 at 02:50
  • 1
    I updated the code above to show more. I called locationAuthStatus() in the viewDidAppear. – iNick Jan 26 '17 at 02:56

3 Answers3

3

I think you code ignores that some of the location operations are asynchronous.

  1. You are calling requestWhenInUseAuthorization and immediately after that do a recursion. requestWhenInUseAuthorization is asynchronous and returns immediately. The status does not change before you do the recursion, so that you call it repeatedly. I suspect that this is the problem causing the error. Use didChangeAuthorization here.
  2. The way you read location using locationManager.location is also suspicious. You should get the location asynchronously to get current location. You should use requestLocation()

Read about CLLocationManagerDelegate to see how to handle asynchronous operations in CoreLocation

MirekE
  • 11,515
  • 5
  • 35
  • 28
  • This was exactly the problem ! I transferred everything to the didChangeAuthorization function and everything worked flawlessly. Thank you for your suggestion – iNick Jan 26 '17 at 14:44
  • @iNick transferring all? what does it mean what did you transfer inside that function? please help. – Sheikh Wahab Mahmood Mar 28 '23 at 10:54
1

EXEC_BAD_Access is indicative of a dereferencing an illegal memory address. In this instance the memory address is that of location manager. To diagnose the problem we need to know where the location manager is created.

Since the problem is not local to the block of code shown, but rather to some earlier point when the location manager was set it is impossible to diagnose the problem from here.

Please provide: 1)Where the location manager property is initially set 2)Anywhere the location manager is changed.

Also insure that you are not doing anything unusual such as trying to access a property in the middle of an unsafe operation such as a segue.

Insure all your entitlements are configured correctly, and check the stack trace to see if the location manager is calling anything that disappeared out from under it.

awiebe
  • 3,758
  • 4
  • 22
  • 33
  • I updated the code above to show more. My location manager is initialized right above viewDidLoad() – iNick Jan 26 '17 at 02:57
0

Did you add NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription to your Info.plist ?

Without these properties might cause crashing on device

Reference here

Community
  • 1
  • 1
Ryan Wu
  • 5,963
  • 2
  • 36
  • 47