Jason
Jason

Reputation: 21

Pass data from AppDelegate to ViewController

I know this question has been asked a lot but I can't find a similar to my situation. I use Google Maps SDK and I want pass my current location coordinates from app delegate to my ViewController. I know how to pass it with let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate but I want to change my location every time my view loads. So I need my current location ONLY on start.

AppDelegate:

import UIKit
import GoogleMaps
import GooglePlaces

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {

    var window: UIWindow?
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    var currentLocation:CLLocation?
    var locationManager:CLLocationManager?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        GMSServices.provideAPIKey("KEY")
        GMSPlacesClient.provideAPIKey("KEY")
        setupLocationManager()

        return true
    }

    func setupLocationManager(){
            locationManager = CLLocationManager()
            locationManager?.delegate = self
            locationManager?.requestWhenInUseAuthorization()
            locationManager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
            locationManager?.startUpdatingLocation()

        }

    // Below method will provide you current location.
     func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        if currentLocation == nil {
            currentLocation = locations.last
            locationManager?.stopMonitoringSignificantLocationChanges()
            let locationValue:CLLocationCoordinate2D = manager.location!.coordinate

            print(locationValue)//THIS IS WHAT I WANT TO PASS

            locationManager?.stopUpdatingLocation()
        }
    }

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


}

ViewController:

import UIKit
import GoogleMaps

class MapViewController: UIViewController,  GMSMapViewDelegate  {

    @IBOutlet weak var mapView: GMSMapView!

    var location : CLLocationCoordinate2D?


    override func viewDidLoad() {
        super.viewDidLoad()
        print(location)
}


}

Upvotes: 0

Views: 813

Answers (2)

Nero
Nero

Reputation: 193

You could extend CLLocationManagerDelegate on your MapViewController instead, that way you have access to any variable from your view controller

Create new file: MapViewCLLocationExtension.swift

import Foundation
import UIKit
import GoogleMaps
import GooglePlaces
extension MapViewController: CLLocationManagerDelegate {

    ...

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

        if currentLocation == nil {
            currentLocation = locations.last
            locationManager?.stopMonitoringSignificantLocationChanges()
            let locationValue:CLLocationCoordinate2D = manager.location!.coordinate

            //print(locationValue)//THIS IS WHAT I WANT TO PASS
            location = locationValue
            locationManager?.stopUpdatingLocation()
            //You should call a method here for any further thing you need to 
            //do with location. DO NOT USE location on viewDidLoad
            useLocation()
        }
    }

I must warn you tho, you can't print the location on viewDidLoad(), b/c it won't be there yet, you need to move any logic to a method and call it at the point where you are sure its gonna be there.

Hope this helps!

Upvotes: 0

creeperspeak
creeperspeak

Reputation: 5521

If you really want to do it that way you can get your location from AppDelegate every time the view load in your MapViewController like so:

import UIKit
import GoogleMaps

class MapViewController: UIViewController, GMSMapViewDelegate  {

    @IBOutlet weak var mapView: GMSMapView!

    var location : CLLocationCoordinate2D?

    override func viewDidLoad() {
        super.viewDidLoad()
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        self.location = appDelegate.currentLocation
        print(location)
    }
}

I'd argue that AppDelegate really isn't the right place to have this CLLocationManager logic, though. If this is the only UIViewController using the location you might just consider implementing that logic inside MapViewController instead. If it is shared by many screens perhaps you should create a LocationManager class that you implement as a singleton so that all of your UIViewController subclasses have access to the up-to-date location data.

Upvotes: 1

Related Questions