user3246092
user3246092

Reputation: 900

How do I get Location coordinates to update in another class?

I am better organizing my app and am having issues working across classes with CoreLocation. My app detects an iBeacon and then sends its coordinates to an API.

In the AppDelegate, I am calling RunLocation().RunGPS() which triggers createLocationManager which triggers it to update the coordinates and send them to the API. My console output prints out everything it should through "Updating Location". Then there is nothing regarding Longitude and Latitude leading me to believe I've screwed something up there, but I have no idea what.

It works when I have it clumsily all put together in ViewController. I'm thinking I'm screwing something up now that's it's been broken up into separate classes.

Relevant code:

    func runGPS(){
        print("Running GPS")
        createLocationManager(startImmediately: true)
    }

    func createLocationManager(startImmediately startImmediately: Bool){
        locationManager = CLLocationManager()
        onSwitch = true
        if let manager = locationManager
        {
            print("Successfully created the location manager")
            manager.delegate = self
            if startImmediately
            {
                if onSwitch == true {
                    manager.startUpdatingLocation()
                    print("Updating Location")
                }else{
                    print("Off")
                }
            }
        }
    }

    func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation){
//        Stop updating location is onSwitch is false. If true, user has called for help. Turn on GPS and execute a post to the API
        if onSwitch == false
        {
            locationManager.stopUpdatingLocation()
            print("Location updates off")
        }
        else
        {
            loadCoreData()
            loadUser()
            print("Updating location")

            let latitude:String = "\(newLocation.coordinate.latitude)"
            let longitude:String = "\(newLocation.coordinate.longitude)"

            print("Latitude = \(newLocation.coordinate.latitude)")
            print("Longitude = \(newLocation.coordinate.longitude)")

            //Posting to the API which generates a map and sends SMS messages
            post(["device_id":"\(deviceID)", "sender":"\(username)", "longitude":"\(longitude)", "latitude":"\(latitude)", "contacts":"\(phoneArray)"], url: "http://ring-api.herokuapp.com/api/v1/alerts")

            //API has been called so stop posting
            onSwitch = false
        }
    }

Console output:

2016-03-22 10:39:14.689 MangosBeta0.4[1531:677382] You entered the region
Running GPS
Successfully created the location manager
Updating Location

Upvotes: 0

Views: 522

Answers (3)

Mathew Spolin
Mathew Spolin

Reputation: 371

One manageable way to do this is to break out location management into a separate class, maybe called LocationController, and instantiate it as a singleton instance in the init method.

public class LocationController {
  static let sharedInstance = LocationController()

}

Then you can instantiate it from your AppDelegate and reference it from any controller in your app. In your ApplicationDidFinishLaunchingWithOptions:

self.locationController = LocationController()

Have your LocationController get callbacks from the locationManager and then distribute the information appropriately to other parts of your app using NSNotifications.

View controllers interested in updates can register for them:

func viewDidLoad (...) {
    NSNotificationCenter.defaultCenter().addObserver(self, selector:"locationChanged:", name: "locationChanged", object: nil)
}

func locationChanged(notification: NSNotification?) {
    guard let data = notification?.userInfo?["data"] as? YourData else {return}
}

And then post stuff from your location controller:

let userInfo = ["data": mydata] 
NSNotificationCenter.defaultCenter().postNotificationName("locationChanged", object: nil, userInfo: info)

Upvotes: 0

Durga Vundavalli
Durga Vundavalli

Reputation: 1828

Your delegate methods are not being called.I think before calling startUpdatingLocation you missed out calling requestAlwaysAuthorization() or requestWhenInUseAuthorization(). Edit your info.plist file to add the following NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription

Upvotes: 1

Dare
Dare

Reputation: 2587

If you keep the location manager as an instance variable, you can access them from anywhere by accessing the current application's delegate property like this.

if let delegate = UIApplication.sharedApplication().delegate as? AppDelegate {
  let manager = delegate.locationManager
}

The reality though is that if you are trying to improve your app architecture, I would not personally put the location logic in your app delegate. That feels like the wrong decision to me. If I were you, I would make a LocationManager singleton class to address both issues.

If you need dependent classes to update in real-time, I would post an NSNotification and listen for it on the classes that need to update.

Upvotes: 2

Related Questions