title: Region Monitoring (Geofencing) drains battery (iOS)
body: <p>I've implemented in my app the region monitoring feature of <code>CLLocationManager</code>, it works but it kills my battery:</p>
  
  <p>-</p>
  
  <p><a href="https://i.stack.imgur.com/qGxQ4.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/qGxQ4.png" alt="Image"></a></p>
  
  <p>-</p>
  
  <p>Is it should be like that?</p>
  
  <p>My code:</p>
  
  <p><strong>monitorLocationViewController.m</strong> (please scroll to see the full code):</p>
  
  <pre><code>-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray&lt;CLLocation *&gt; *)locations
  {
      //If "allStores"(NSMutableArray) isn't nil - calling "locationChangeHandler" to update monitoring
      if (self.allStores!=nil) {
          [self locationChangeHandler];
      }
  
      CLLocation *currentLocation=(CLLocation*)[locations lastObject];
      NSSet *monitoredRegionsSet=self.locationManager.monitoredRegions;
      [monitoredRegionsSet enumerateObjectsUsingBlock:^(CLCircularRegion *region, BOOL *stop) {
          if ([region containsCoordinate:currentLocation.coordinate]) {
              [self.locationManager stopMonitoringForRegion:region];
              [self locationManager:self.locationManager didEnterRegion:region];
          }
      }];
  }
  
  -(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
  {
       Store *store=[self storeForRegion:region];
      if (store.alreadySendNotification==NO) {
          UILocalNotification *notification=[[UILocalNotification alloc] init];
          notification.alertTitle=@"Arounder";
          notification.alertBody=[[self storeForRegion:region] address];
          [[UIApplication sharedApplication] scheduleLocalNotification:notification];
  
          store.alreadySendNotification=YES;
      }
  }
  
      //For updating monitoring
  -(void)locationChangeHandler
  {
  //If "allStores"(NSMutableArray) isn't nil
      if (self.allStores!=nil) {
          //Finding the 20 closest stores to he user's location and adding it to "twentyClosestStores"(NSMutableArray)
          [self sortClosestStores];
          //Stop monitoring "previousTwentyStores"(NSMutableArray) (20 closest stores before user's location  updated)
          [self stopMonitoringStores];
          //Start monitoring "twentyClosestStores"(NSMutableArray)
          [self startMonitoringClosestStores];
      }
  }
  
  //Start monitoring "twentyClosestStores"(NSMutableArray)
  -(void)startMonitoringClosestStores
  {
      //If monitoring isn't availible for "CLCircularRegion"
      if (![CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) {
          NSLog(@"Monitoring is not available for CLCircularRegion class");
          return;
      }
  
      //Run on all "twentyClosestStores"(NSMutableArray)'s objects
      for (Store *currentStore in self.twentyClosestStores) {
          //Start monitoring "region"(CLCircularRegion)
          [self.locationManager startMonitoringForRegion:currentStore.circularRegion];
      }
  }
  
  //Stop monitoring "previousTwentyStores"(NSMutableArray) (20 closest stores before user's location  updated)
  -(void)stopMonitoringStores
  {
      //Run on all "monitoredRegions"(NSSet) of "locationManager"(CLLocationManager) objects
      for (CLCircularRegion *currentRegion in self.locationManager.monitoredRegions) {
          //Stop monitoring "region"(CLCircularRegion)
          [self.locationManager stopMonitoringForRegion:currentRegion];
      }
  }
  
  //Finding a store for region
  -(Store*)storeForRegion:(CLCircularRegion*)region
  {
      //Run on all "allStores"(NSMutableArray)'s objects
      for (Store *currentStore in self.allStores) {
          //If "currentStore"(Store)'s "circularRegion"'s identifier is equal to "region"(CLCircularRegion)'s identifier
          if ([currentStore.circularRegion.identifier isEqualToString:region.identifier]) {
              //Returning "currentStore"(Store)
              return currentStore;
          }
      }
      //Store not found - returning nil
      NSLog(@"No store found for this region: %f,%f",region.center.latitude,region.center.longitude);
      return nil;
  }
  </code></pre>
  
  <p><strong>AppDelegate.m</strong>:</p>
  
  <pre><code>-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
      self.monitorLocationVC=[[monitorLocationViewController alloc] init];
      self.monitorLocationVC.locationManager=self.locationManager;
  
      [self configureLocationManager];
      [self.locationManager startUpdatingLocation];
  
      return YES;
  }
  
  -(void)configureLocationManager
  {
      //Initializing locationManager
      self.locationManager=[[CLLocationManager alloc] init];
      //setting "locationManager"'s(CLLocationManager) delegate to "self"
      self.locationManager.delegate=self.monitorLocationVC;
      //Setting "locationManager"'s(CLLocationManager)'s distance filter to none
      self.locationManager.distanceFilter=kCLDistanceFilterNone;
      //Setting "locationManager"'s(CLLocationManager)'s activityType to navigation
      self.locationManager.activityType=CLActivityTypeAutomotiveNavigation;
      //setting "locationManager"'s(CLLocationManager) desiredAccuracy to "best"
      self.locationManager.desiredAccuracy=kCLLocationAccuracyBestForNavigation;
  
      self.locationManager.pausesLocationUpdatesAutomatically=NO;
  
      //If OS version is 9 or above - setting "allowsBackgroundLocationUpdates" to YES
      if ([[[UIDevice currentDevice] systemVersion] floatValue] &gt;= 9) {
          self.locationManager.allowsBackgroundLocationUpdates = YES;
      }
  }
  </code></pre>
  
  <p>Thank you!</p>