Reputation: 900
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
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
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
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