Volker88
Volker88

Reputation: 654

Using Variable outside locationManager()

I'm trying to clean up my code using MVC Pattern. I have one file "CoreLocationService.swift" where I want to get the location. I want to use the location then in "ViewController.swift" to show it to the user.

CoreLocationService.swift

import Foundation
import CoreLocation

class CoreLocationService: CLLocationManager, CLLocationManagerDelegate {


    let locationManager = CLLocationManager()

    var latitude : Double?


    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let GPS = locations[locations.count - 1] // Get the array of last location

        latitude = GPS.coordinate.latitude


    }
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
    }


    func GPSInitialize() {
        // Start GPS

        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        //locationManager.requestLocation() // One time request
        locationManager.startUpdatingLocation() // Continues location

    }


}

ViewController.swift

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

//    let location = CLLocationManager()

    let locationService = CoreLocationService() // CoreLocationService Class


    override func viewDidLoad() {
        super.viewDidLoad()


        locationService.GPSInitialize() // Start updating Location


        print(locationService.latitude) // Print Latitude

    }

}

i declared latitude as a global variable to access is from ViewController.swift but the variable it empty and prints only "nil".

If I print "Print(latitude)" within locationManager it prints the coordinate.

Upvotes: 0

Views: 339

Answers (2)

BhargavR
BhargavR

Reputation: 1133

In your code, viewDidLoad() function will call the GPSInitialize() function in the CoreLocatinoService class. At this time when it executes the next line of code, 'latitude' value will be nil cause the delegate method of CLLocationManager 'didUpdateLocation' might not get called right away as soon as the startUpdatingLocation() is called.

As a solution of this I would suggest to have another delegate or closure which informs the view controller about the location update and pass the latest location details.

Hope this helps.

Upvotes: 0

Michael Wang
Michael Wang

Reputation: 10203

I think why the latitude is nil when you call print(loccationService.latitude) is that the delegate method

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

has not updated the latitude yet.

You could add one callback in CoreLocationService like below,

// callback to be called after updating location
var didUpdatedLocation: (() -> ())?

and then call this closure in the delegate method,

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let GPS = locations[locations.count - 1] // Get the array of last location

        latitude = GPS.coordinate.latitude

        didUpdatedLocation?()
}

In your ViewController, print the latitude like this,

locationService.didUpdatedLocation = {
    print(locationService.latitude) // Print Latitude
}

Hope this helps!

Upvotes: 1

Related Questions