DidEnterRegion works in the foreground, but not background or other VC

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.

+7
source share
4 answers

My friend wrote a good tutorial on using a geo lens that can help fix some of the problems you have.

Start with geoprocessing

There are many examples online and here on SO. Start small and take your way up. Once you start receiving callbacks, you can start expanding access to your other view controllers.

UPDATE

As explained in the comments, the benefits of creating a singleton class to manage your location manager and delegation methods. Using singleton mode, you prevent multiple delegate methods from getting multiple calls. You can prevent this by carefully coding, but using singleton does this for you. It is also a good class to handle all the work that needs to be done using your delegation methods.

+3
source

Things you do wrong:

  • Backgrounds - Application registers for location updates. It is not necessary. This is necessary when you want to collect information about significant changes in location, etc. So, go to "Goals"> "Application"> "Capabilites" and select the option you want in the "Backgrounds". This will automatically update the plist for you. Disable it for now.
  • You are trying to create an alert when a user enters a region. Although this works when the application is running, a warning does not make sense when your application is in the background. Do. Rather, call a local notification or call api.

eg. notifications:

  -(void)triggerLocalNotification:(CLRegion *)region{ UILocalNotification *notification = [[UILocalNotification alloc]init]; [notification setAlertBody:[NSString stringWithFormat:@"Welcome to %@", [region identifier]]]; [notification setRepeatInterval:0]; [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:2]]; [notification setTimeZone:[NSTimeZone defaultTimeZone]]; [[UIApplication sharedApplication]scheduleLocalNotification:notification]; NSLog(@"notification triggered with notification %@", notification); } 
+2
source

You can post a local notification when you made an EnterRegion.

This will show a reminder popup, even if you are in the background.

You can do a simple test:

1) Create a local notification object inside your application's DidEnterBackground of your application delegate with any random message and immediately inform the local notification.

2) Press the "home" button, when you hide the application, you will see a pop-up window.

0
source

I think you need to go to your app.plist

and add the required background modes: add itme Application registers for updating the location

and 1. if the application is in the background, you still see the arrow above

and 2, if the application is killed, you can still see the hollow arrows on top, ios will control the region for you, but limited to 20 regions

0
source

All Articles