If the application is running and the CLLocationManagerDelegate class is front (i.e. visible), then didEnterRegions starts and I get both NSLog and AlertView. However, I get nothing when the application is in the background or, in fact, if nothing is displayed on the screen except the delegate class.
I set the "Application Register for location updates" in the "Required Backgrounds" section of the plist, although I'm not sure even that is necessary.
Here I think this is the appropriate code, although I may be wrong (and I will add more with pleasure). I should note that everything in viewDidLoad is wrapped in if if it checks if monitoring is available and if area monitoring is enabled.
- (void)viewDidLoad { NSLog(@"MapViewController - viewDidLoad"); self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; self.locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters; self.locationManager.delegate = self; [self.locationManager startMonitoringSignificantLocationChanges]; } - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { NSLog(@"MapViewController - didEnterRegion"); NSLog(@"MVC - didEnterRegion - region.radius = %f", region.radius); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"entered region..." message:@"You have Entered the Location." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; alert.tag = 2; [alert show]; }
here I get a list of controlled regions, in AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // other code NSLog(@"LISTING ALL REGIONS MONITORED"); NSArray *regions = [self.locationManager.monitoredRegions allObjects]; if (!regions) { NSLog(@"no regions found"); } else { NSLog(@"got %d monitored regions", [regions count]); for (int i = 0; i < [regions count]; i++) { CLRegion *region = [regions objectAtIndex:i]; NSLog(@"region %d identifier = %@", i, region.identifier); NSLog(@"region: radius: %@", region.radius); } } // other code }
I call startMonitoringForRegion twice, here is the main place:
- (void)doneButtonTapped { NSLog(@"doneButtonTapped"); if (self.locationIdentifier) { if ([CLLocationManager regionMonitoringEnabled] && [CLLocationManager regionMonitoringAvailable]) { // core data setup NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"LocationReminder" inManagedObjectContext:self.managedObjectContext]; fetchRequest.entity = entityDescription; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"locationIdentifier == %@", self.locationIdentifier]; fetchRequest.predicate = predicate; NSError *error; NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; if (results) { // get the LocationReminder LocationReminder *retrievedReminder = [results objectAtIndex:0]; retrievedReminder.audioURI = [[[self.audioPlayers objectAtIndex:self.selectedCell] url] absoluteString]; retrievedReminder.userRecording = nil; // start monitoring it region NSArray *coordinateArray = [retrievedReminder.locationIdentifier componentsSeparatedByString:@", "]; CLLocationCoordinate2D coordinate = {[[coordinateArray objectAtIndex:0] doubleValue], [[coordinateArray objectAtIndex:1] doubleValue]}; CLRegion *newRegion = [[CLRegion alloc] initCircularRegionWithCenter:coordinate radius:250.0 identifier:retrievedReminder.locationIdentifier]; NSLog(@"about to monitor region with radius: %f", newRegion.radius); [self.locationManager startMonitoringForRegion:newRegion desiredAccuracy:kCLLocationAccuracyBest]; // save the LocationReminder if (![self.managedObjectContext save:&error]) { NSLog(@"hmm. no managed object context. must be something space-time going on"); } else { NSLog(@"saved locationReminder, locationIdentifier = %@", retrievedReminder.locationIdentifier); } } else { NSLog(@"ERROR: no LocationReminder retreived for predicate: %@", predicate); } } // get the mapview controller off of the navigation stack for (UIViewController *viewController in self.navigationController.viewControllers) { if ([viewController isKindOfClass:[MapViewController class]]) { MapViewController *mapVC = (MapViewController *)viewController; mapVC.audioURI = [[[self.audioPlayers objectAtIndex:self.selectedCell] url] absoluteString]; [self.navigationController popToViewController:mapVC animated:YES]; } } }
And since I get the feeling that this might be important, here's the getter for the locationManager:
- (CLLocationManager *)locationManager { NSLog(@"MapViewController - locationManager"); if (_locationManager) { return _locationManager; } else { _locationManager = [[CLLocationManager alloc] init]; return _locationManager; } }
UPDATE 1: Through the Apple forums (where I cross-checked), someone mentioned that AlertView will only display in the foreground. However, NSLog does not work. I guess this should work.