0

I have a big problem. With iOS 7.1, it's possible to monitor the enter/exit of a beacon region even if the app is closed (not in background, but completely closed).

But I notice that this is possible only if the beacon delegates are in the main controller, and not if they are in other controllers (for example called in modal way).

My app for example is built with:

appDelegate --> firstController --> secondController

If I put the beaconManager and its delegates in the firstController, they will be called also with the app closed, while if I do the same in the second controller (presented as modal viewController) they are not called (they work only in foreground or in background).

How is it possible to fix this problem?

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
  • I'm coding some stuff with this currently and don't think I have the problem. Will look and see how I handle it and post here later – Cocoadelica May 12 '14 at 16:30

2 Answers2

0

An common way to address this issue is to exclusively use your AppDelegate as the CLLocationManager delegate. In the callback methods in the AppDelegate, you check to see which ViewController (if any) is active at any given time and make calls to that ViewController from the callback methods as needed.

In order to do this, you must make a property on your AppDelegate for each ViewController that uses CoreLocation services:

@interface MyAppDelegate : UIResponder <CLLocationManagerDelegate>
@property (strong, nonatomic) FirstViewController *firstViewController;
@property (strong, nonatomic) SecondViewController *secondViewController;
@end

And then set the corresponding property when your ViewController loads. Like this:

- (void)viewDidLoad
{
    [super viewDidLoad];
    MyAppDelegate *appDelegate = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
    appDelegate.firstViewController = self;
    ...
}

Once you have this done, you can have your callbacks registered exclusively in your MyAppDelegate, but pass them off to individual ViewControllers like this:

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    if (self.firstViewController != Nil) {
        [self locationManager:manager didEnterRegion:region]; 
    }
}
davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • Thank you David, I understood the concept...but do I create the CLLocationManager instance in myAppDelegate or in myViewController? In my opinion I should create the CLLocationManager instance in myViewController and put the delegate to myAppDelegate e start monitoring...is it right? So CLLocationManager *manager = [[CLLocationManager] alloc] init]; manager.delegate = (AppDelegate *) [[UIApplication sharedApplication] delegate]; [manager startMonitoringForRegion:myRegion]; and then from myAppDelegate i make the callback to my viewController... – Carlito El Peralta May 13 '14 at 10:52
  • I would do all this in `AppDelegate#viewDidLoad` because it will keep things simpler and it is the only real way to guarantee background operation. The ViewController methods may not get called in the background. – davidgyoung May 13 '14 at 11:08
0

What I am doing when dealing with CLLocationManager is the following:

  • I create a class that implements a singleton pattern that acts as the delegate in for the CLLocationManager callbacks.
  • Then I create a protocol that uses the delegate methods that I want to forward to a specific view controller
  • I implement the protocol methods in the required view controllers.
  • in the AppDelegate (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method I instanciate singleton for the first time so that the CLLocationManager and the UUIDs get registered
  • When a callback from the CLLocationManager arrives at one of my registered view controllers I check if my App is currently active and than handle the callback accordingly

    UIApplicationState state = [application applicationState];
    if (state == UIApplicationStateActive) {
    // Application is in foreground
    }
    
Argent
  • 390
  • 1
  • 3
  • 11
  • Thank you but I resolved putting all beacon methods in myAppDelegate and activating them from mySecondController for the first time. At that time monitoring works also with the app closed. – Carlito El Peralta May 14 '14 at 07:07