1

I'm having a bit of trouble getting this right. What i have is a NavigationController with several View Controllers. In the first View Controller i instantiate a new class, GPSTrackingManager:

var tracking = GPSTrackingManager()

Because i need GPS data and functions available in all view controllers after this UINavController. I'm calling this already in the first VC so the GPS can get a early fix. How can i pass this tracking object to the new view controllers? I tried several things in the prepareForSegue, but i'm out of ideas currently. If i put the above code in the new VC then i have the startUpdatingLocation() running 2 times. If you can point me in the right direction that would be greatly appreciated!

EricDXS
  • 882
  • 9
  • 11

2 Answers2

2

I think the most appropriate solution (without going too overboard, because there are certainly more thorough ways to go about this problem) is to separate the gps management into its own singleton class, and to subscribe to a trackerUpdated protocol for updates.

import Foundation
import placeWhereGPSTrackingManagerIs

protocol GPSManagerDelegate {
    func didUpdateTracker(tracker: yourTrackerObject)
}


let _GPSManagerSharedInstance = GPSManager()



class GPSManager {

weak var delegate: GPSManagerDelegate?
let tracker: yourTrackerObject?

class var sharedInstance:GPSManager {
    return _GPSManagerSharedInstance
}

init() {
    tracker = GPSTrackingManager()
    tracker.startUpdatingLocation()
}

func updateTracker(newInformation) // you'll want to pass whatever information your tracker needs here
{
    tracker.trackerProperty = newInformation
    self.delegate?.didUpdateTracker(tracker)
}

}

Swift singleton explanation Using a dispatch_once singleton model in Swift

Now, whatever startUpdatingLocation does could call updateTracker in this class with the new information it needs to update the tracker. You could also migrate that logic to live inside of here (which I recommend doing in this case) so everything is contained in one class.

Any view controller interested in the information can subscribe to the didUpdateTracker protocol method, which will pass the tracker through to that view controller

import UIKit


class controllerOne: UIViewController, GPSManagerDelegate {

override func viewDidLoad() {
    super.viewDidLoad()
    GPSManager.sharedInstance.delegate = self // set the GPSManager delegate
    if let tracker = GPSManager.sharedInstance.tracker {
    // if the tracker exists, we assign it to the "tracker" variable, and use as needed
    // setup page with tracker

    }

}

func didUpdateTracker(updatedTracker: yourTrackerObject) {
    // protocol method that will be called from the gpsmanager everytime it updates
    // do whatever updates to the page with the 
}

}

As you can only have one GPSManager and its tracker property cannot be changed, it is always safe to ask the GPS manager for this tracker, which only calls startUpdatingLocation() on its initialization

You could also post notifications as @shesh nath mentioned, which is a perfectly valid way to broadcast changes if you prefer it to the delegation method. Either way you approach it, I would recommend separating the tracker from the view controller so that the view controllers are not the ones in charge of managing the trackers state.

Community
  • 1
  • 1
domitall
  • 655
  • 5
  • 15
  • Thank you :) I used your examples to build this into my classes and it is working perfectly now. I can access the values from the GPSTrackingManager in all View Controllers without creating a new(duplicate) instance. I'm going to read more about protocols in Swift. – EricDXS Oct 15 '14 at 11:23
  • Awesome! Glad I could help, <3 protocols – domitall Oct 15 '14 at 14:12
0

There are several ways to achieve it like 1) using Key-Value observer 2) Notification

Example of Notification is on your first viewController post notification and pass your data to this notification.

NSDictionary *data;
 [[NSNotificationCenter defaultCenter] postNotificationName:@"updateBeaconStateOnDetailScreen" object:data];

and on left-over all viewcontroller register listener for this notification on viewdidload example.

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateBeaconState:)name:@"updateBeaconStateOnDetailScreen" object:nil];

and your method which will be called by this notification is

  -(void) updateBeaconState:(NSNotification *) notification
 {   //notification raised from BeaconList with updated Beacon State
    NSDictionary *dictUpdatedBeacon=[notification valueForKey:@"object"];
 }
Sheshnath
  • 3,293
  • 1
  • 32
  • 60