iOS 7.1 Geofencing and iBeacons stop working - ios

I am working on a location services app and am finding some strange behavior. Once the user confirms using location services, the geofence icon appears in the status bar. Everything works great and I get enter and exit region events whether the app is running, in the background, or not in the background. But at some point the geofence icon disappears and my device is insensitive to the Beacon. Are there any conditions under which the geofence is disabled until I power cycle the device? And power cycling does bring it back.

This is a newly introduced bug in CoreLocation. Unfortunately, there is no known automated way to fix this. It requires a power cycle or Bluetooth off/on sequence to resolve.
See here.

I was having a similar problem. My app would work and locate beacons on initial run. When I rebooted, app opened to ScanViewController as expected but did not detect beacon.
I referenced article on StackOverflow, iBeacon: didRangeBeacons stops getting called, must reset device for it to work again and reviewed Apple's WWDC 2013 Video Session "What's new in Corelocation" https://developer.apple.com/videos/wwdc/2013/index.php?id=307
I found additional CLLocation delegate methods:
When you init your beacon region if you set:
notifyEntryStateOnDisplay = YES;
//The following delegate method will be called:
-(void) locationManager: (CLLocationManager *) manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if (state ==CLRegionStateInside) {
[_locationManager startRangingBeaconsInRegion:region]:
}
//Your alternative code
}
//To help trouble shoot, I added this delegate methods
-(void) locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *) region withError: (NSError *)error {
}
and
-(void) locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion:(CLRegion *) region withError: (NSError *)error {
}
I ran app. It returned no failure errors. I checked settings. Bluetooth was enabled and detecting BT devices.
I checked the status bar for geofencing icon. The geofencing icon was present.
I waited for over 2 minutes and then the app detected the beacons and worked as expected. Sluggish is an understatement. I knew that rebooting should work according to all the iOS 7.1 articles that I read in StackOverFlow and other resources.
I rebooted and waited for the app to detect the beacons. On average it took 2 minutes until beacon detection. I am not sure what is causing this slow response. Since must app responses are measured in fractions of seconds, I am sure that developers may think that their apps are not working.
I suggest if your app does not detect beacons or return failure errors that you wait 2 minutes to see if you app will detect the beacon(s). I hope this helps.

Related

iOS 9 Defer location update not working

Hi recently with the iOS 9 GM seed version out,I have seen location update(allowDeferredLocationUpdatesUntilTraveled:timeout:) not getting deferred. I am getting error kCLErrorDeferredFailed - The location manager did not enter deferred mode for an unknown reason.
Its because of this error its not entering the defer mode at all and location updates are firing continuously .
The same code used to work in iOS 8.4 and below versions.Its draining my device's battery by a huge percentage.
Is there anything we need to explicitly set or mention for iOS 9.Didn't find anything from Apple documentation?
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
if (!self.deferringUpdates) {
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:30];
self.deferringUpdates = YES;
}
}
-(void)locationManager:(CLLocationManager *)manager
didFinishDeferredUpdatesWithError:(NSError *)error {
// Stop deferring updates
self.deferringUpdates = NO;
}
I also set the allowsBackgroundLocationUpdates property but even that didn't help.
self.locationManager.allowsBackgroundLocationUpdates=YES;
In iOS 9 and later, regardless of deployment target, you must also set the allowsBackgroundLocationUpdatesproperty of the location manager object to YES in order to receive background location updates. By default, this property is NO, and it should remain this way until a time when your app actively requires background location updates.
Reduce Location Accuracy and Duration
Please let me know what additional I need to make
Thanks
Please read the discussion on the API reference page.
A few things to try, as mentioned here
Kill all apps from multitasking bar
Verify that no other app is using location services
Unplug the device from debugger and MacBook (Verify it is still getting call by logging didUpdateLocations to a file)
Make sure that the device supports deferred updates
Make sure that the distanceFilter is None, the desiredAccuracy is Best

ios deferred location updates fail to defer

I am looking into using deferred location updates for an iOS activity tracker, which allows location services in background. I've implemented the suggested code snippets (see below). In Xcode debugging, deferred locations attempt to start a few times until location data comes in at about 1 per second. After that, it claims to succeed in starting deferrals, and the callback for the finish trigger also succeeds after the specified time period expires. However during the time, the location handler still runs once per second. I've read that this is because the phone hasn't deemed itself ready to enter the background, and that testing in Xcode does this. Note, AppDelegate's "didEnterBackground" eventhandler got called immediately when turning off the screen, and resumed when reopening app.
I ran the same code with the phone disconnected as another test, near the window with GPS, screen off, or switching to entirely different apps, and it still never actually defers the updates. I can tell because the networked update still comes in once every 30 seconds, instead of the interval of 120 seconds which is desired in the code sample below.
What else is needed to actually get deferrals to work, since there is no error occurring in starting them and they do get their finish callback? Why do location updates continue at 1 per second even when the app goes to background?
Iphone 5s, IOS 7.1.1
// .h file (partial)
#interface MotionTracker : NSObject<CLLocationManagerDelegate, UIAccelerometerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
// .m file (parial)
- (id) init {
if(self = [super init]){
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// if set to YES (default), app stops logging location at some point and doesn't resume in any timely fashion, all data points lost in between
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeFitness;
}
return self;
}
// called early in program after login confirmed
- (void) startCollectingLocation {
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// logs to file when device is not in debug
// always returns 1
NSLog(#"Location update count: %d",[locations count]);
// some code here to handle location updates
// - collect key location day in NSDictionary
// - every N seconds send Network call to server to save (have tried 30 seconds, 15 minutes, 30 minute network intervals). Have also tried turning off network calls completely.
// deferred updates starter
if (!self.deferringUpdates) {
if([CLLocationManager deferredLocationUpdatesAvailable]){
[_locationManager allowDeferredLocationUpdatesUntilTraveled:500 timeout:(NSTimeInterval)120]; // (have also tried large numbers, and "Infinite"
self.deferringUpdates = YES;
NSLog(#"Deferred updates start");
} else {
NSLog(#"Deferred updates not available");
}
}
}
- (void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
if(!error){
_deferringUpdates = NO;
NSLog(#"Deferred updates: finished");
} else {
_deferringUpdates = NO;
NSLog(#"Deferred updates: %#", [error localizedDescription]);
}
}
If the device is connected to a debugger or on a charger, the device will remain powered (not sleep) and therefore will not enter deferred mode. Deferred mode is a power optimization allowing the device to sleep. If the device is not scheduled to sleep for other reasons, enabling deferred mode will not force it to sleep otherwise. Try your test by ensuring no other apps are using location services, and disconnecting it from a charger with the screen off. After running for some time, plug back in and check your logs, you should see that the device slept and deferred updates.
From Apple's
allowDeferredLocationUpdatesUntilTraveled:timeout: documentation:
Deferred updates are delivered only when the system enters a low power
state. Deferred updates do not occur during debugging because Xcode
prevents your app from sleeping and thus prevents the system from
entering that low power state.
It is also worth noting that deferred updates are only available when locationManager.desiredAccuracy is set to kCLLocationAccuracyBest OR kCLLocationAccuracyBest; locationManager.distanceFilter must also be set to kCLDistanceFilterNone.
From Apple's documentation:
...the location manager allows deferred updates only when GPS hardware is available on the device and when the desired accuracy is set to kCLLocationAccuracyBest or kCLLocationAccuracyBestForNavigation.
and
...the distanceFilter property of the location manager must be set to kCLDistanceFilterNone.
I have been struggling with the same issue, and I may have found an answer that solves this problem for many - at least it solves my problem and gets deferred updates working consistently for me.
I followed all of the steps in this list and no matter what I did, location updates would not defer. It occurred to me that I might have other apps running that were not allowing the system to sleep, so I killed all other apps in the multitasking tray. I ran my sample app again and ... it worked!
But the story doesn't end there. I tried again a little later, and even though there were no other apps running in the multitasking tray I couldn't get location services to defer. Then it occurred to me that I have an app on my phone called "Moves" which manages to keep itself alive even after you manually kill it. I'm not entirely sure how Moves comes magically back to life when you kill it, but it does (perhaps using bluetooth and the app preservation / restoration service). Even though it is alive and tracking your location it doesn't appear in the multitasking tray. I think that only apps that are manually launched appear in the tray - if the OS launches an app it doesn't appear in the tray. But I digress ...
I was able to get deferred location services to work consistently in my app by disallowing Moves to use location services. When I did, Moves complained even though it wasn't in multitasking tray. It seems that if another app is using location services (and not deferring) your app won't defer either.
Hi recently with the iOS 9 GM seed version out,I have seen location update(allowDeferredLocationUpdatesUntilTraveled:timeout:) not getting deferred.The same code used to work in iOS 8.4 and below versions.Its draining my device's battery by a huge margin.
Is there anything we need to explicitly set or mention for iOS 9?Didn't find anything from Apple documentation
Here is the code that I implemented.
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
if (!self.deferringUpdates) {
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:30];
self.deferringUpdates = YES;
} }
-(void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error { // Stop deferring updates self.deferringUpdates = NO;
}
I also set the allowsBackgroundLocationUpdates property but even that didn't help. self.locationManager.allowsBackgroundLocationUpdates=YES;
In iOS 9 and later, regardless of deployment target, you must also set the allowsBackgroundLocationUpdatesproperty of the location manager object to YES in order to receive background location updates. By default, this property is NO, and it should remain this way until a time when your app actively requires background location updates.
https://developer.apple.com/library/prerelease/ios/documentation/Performance/Conceptual/EnergyGuide-iOS/LocationBestPractices.html
Please let me know what additional I need to make
Thanks

iBeacons ranging in background sometimes has delay

I have an iBeacons app able to range for beacons while in background or not running. I implemented UILocalNotifications and they work fine, meaning i get a notification when i reach the range of a beacon.
Not having a real beacon i created an app (for another device, let's say an iPad for the next scenario) that acts like 2 different beacons, meaning it can broadcast 2 different signals, same UUID but different Major/Minor values (call this beacon A and B), one at a time obviously. My problem is in this scenario:
Have my iPhone (with iBeacons app closed) in lock screen
Activate my iPad app, broadcasting beacon A
My iPhone reacts showing me a notification
I stop iPad app from broadcasting beacon A, wait 1 second, start broadcasting beacon B
My iPhone DOESN'T react
I stop iPad from broadcasting
A few minutes later (about 2) my iPhone shows me the notification of beacon B
Now what i don't understand is this delay, the first time my iPhone reacts immediately, the second time it takes about 2 minutes to notify me the beacon.
If, after beacon B notification, i re-start broadcasting a beacon (A or B) my iPhone reacts immediately, then for the next time it always waits for 2 minutes.
Why is this happening? I've read some article saying that it's because the bluetooth awakes every 2-4 minutes while the app is in background, so i can get the info not faster than this time. But i don't see much sense in this because whenever i get the second notification the broadcasting of the beacon (B in my scenario) was already stopped, it means that if the bluetooth awakes in that very moment no beacon was in the air! But i get the notification, so it means that in someway my iPhone found it before i stopped the broadcasting.
Is this a problem that can be solved?
EDIT with some code
Here is my viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize location manager and set ourselves as the delegate and beacons dictionary
_beacons = [[NSMutableDictionary alloc] init];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Create a NSUUID with the same UUID as the broadcasting beacon
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"6C1AA496-1653-403D-BD1E-7F630AA6F254"];
// Setup a new region with that UUID and same identifier as the broadcasting beacon
self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:#"testregion"];
NSLog(#"startMonitoring");
// Tell location manager to start monitoring for the beacon region
[self.locationManager startMonitoringForRegion:self.myBeaconRegion];
[self.locationManager startRangingBeaconsInRegion:self.myBeaconRegion];
_myBeaconRegion.notifyEntryStateOnDisplay = YES;
// Check if beacon monitoring is available for this device
if (![CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Monitoring not available" message:nil delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil]; [alert show]; return;
}
}
Now whenever i get a beacon i send a notification, i just wanted to try how it worked so i didn't implemented yet a way to send just 1 notification, it means i get about 9 notification, 1 per sec that's the active time the code can run while in background i suppose (1 second enter region, 9 ranging for beacons)
-(void)locationManager:(CLLocationManager*)manager
didRangeBeacons:(NSArray*)beacons
inRegion:(CLBeaconRegion*)region
{
if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground){
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = #"Found Beacon";
notification.soundName = #"Default";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
}
Actually to be more specific, if i totally close my app from the multitasking view, or just let it in background, as soon as i start broadcasting a beacon i get the notification**S** (1 second delay). Then stopping the broadcasting and re-play the delay becomes in the order of minutes.
Now for a real scenario, where i should have many beacons in the same place, this delay could be a problem, as long as i get the notification when i could be already far away from the beacons itself.
Has my code any problem? I read those articles but i never found a delay of 15 minutes.
EDIT2 after davidgyoung suggestions
I modified my code and as you said using 2 different regions for beacon A and B the delay is always null. I also logged with the piece of code you gave and i discovered this.
Broadcast the beacon of Region_1
Device shows me the notification of Region_1
Stop broadcasting the beacon of Region_1
The logs say i'm still in the region, only after a couple of minutes i get the log "OUTSIDE Region_1", just now i can re-play the broadcasting to get another notification from Region_1.
So i was curious about this and i read and article http://beekn.net/2014/03/apple-ios-7-1-launches-major-ibeacon-improvement/
The author says that from iOS 7.1 the responsiveness of exiting a region is immediate, actually i'm running 7.1 but i also have a couple of minutes delay. Why this? Did you find the same problem in your tests?
Now, i read that a device can listen for no more than 20 regions right?it means that if i have 100 beacons i can set up just 20 regions and divide these 100 in 20 groups, getting no more than 20 notification (assuming these 100 are in the same place, all in the range of my device) ? That could be a problem because will force the user to run the app in the foreground to get all the information (assuming again each of the 100 beacons have a particular and unit role), am i right?
EDIT: This is my first answer before seeing the code.
I cannot explain this behavior based on your description, but I suspect there may be an issue with the setup that is either delaying your local notification or inaccurately reporting the state of beacon region B when the notification is sent.
Two things would help verify/eliminate this possible cause:
Add NSLog statements in your didDetermineState: forRegion: callback like below, then repeat your test reporting the log results.
// put this in your AppDelegate
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
if(state == CLRegionStateInside) {
NSLog(#"locationManager didDetermineState INSIDE for %#", region.identifier);
}
else if(state == CLRegionStateOutside) {
NSLog(#"locationManager didDetermineState OUTSIDE for %#", region.identifier);
}
else {
NSLog(#"locationManager didDetermineState OTHER for %#", region.identifier);
}
}
Post the code that sets up monitoring and issues the notification on detection.
If you have not read this already, you may want to give a quick look to similar tests I have done to measure background detection times:
http://developer.radiusnetworks.com/2013/11/13/ibeacon-monitoring-in-the-background-and-foreground.html
http://developer.radiusnetworks.com/2014/03/12/ios7-1-background-detection-times.html
After seeing the code, I think a few issues are going on here:
The code defines only a single region that encompasses BOTH beacon A and beacon B, preventing independent region entry/exit monitoring callbacks, and stopping the phone from getting woken up when switching from transmitting beacon A to beacon B. This is critical, because this means that if you switch from transmitting beacon A to beacon B, iOS will consider itself still in the one region. This can prevent the phone from getting a monitoring event that will wake up the phone in the background.
There is no code in the ranging callback to check which beacon was visible, so it does not seem possible to know for sure which beacon caused the notification. The notification will fire even if the beacon array passed to the ranging callback method is empty (i.e. if no beacons are detected.)
Ranging generally does not work in the background. The only exception is for a few seconds right after entering/exiting a region. I suspect that the two minute delay you report is the time it takes for your iPhone to perform the next background scan for iBeacons (This delay can be 2, 4, or 15 minutes depending on phone state). After that next next scan is performed, a region transition is detected (probably an exit region notification because nothing is transmitting), and ranging starts up for 5 sec firing a notification.
This is all very difficult to test and troubleshoot without directly logging the of the monitoring region callbacks as mentioned in my first answer as well as the ranging callbacks, and logging the identifiers of the beacons detected. Make sure you understand which of these callbacks are firing in order for which beacons, and don't try to troubleshoot too much at once!
In addition to troubleshooting the individual callbacks first, I would also recommend:
Changing the code to have one region per beacon for maximum background responsiveness.
Putting the detected beacon identifiers in the notification so you know beacon caused the notification to fire.
DavidGYoung is correct. iOS7.1 will invoke your app when terminated upon sensing a beacon region traversal. But,and this is critical, iOS will ONLY invoke a terminated app when you ENTER or EXIT a beacon region, and only if your app has previously registered for location events for that particular beacon region.
In your explanation above, it looks like you are only monitoring for ONE beacon region (you did not specify Major/minor numbers so any beacon with the same UUID will qualify). Unfortunately you created two beacon transmitters with the same UUIDs. So when you started the beacon you got ONE notification (ENTER) but had to wait a couple minutes for another (EXIT). typically I've seen exit notifications about 30 sec after a beacon stops transmitting.
If you want to perform the experiment again, try registering for TWO different beacon regions (declare two regions with diff Major/Minor numbers, or make two diff UUIDs), and then use these two diff values in your beacon transmitter. Should work then.
Tom

startMonitoringForRegion doesn't fire didEnterRegion and didExitRegion

I'm doing some test using estimote beacons and regions.
Reading the documentation as I start monitoring a region I'm going to tell my delegate that a specific region is being monitored, however, didEnterRegion and didExitRegion are never fired.
My delegate fires:
-(void)beaconManager:(ESTBeaconManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(ESTBeaconRegion *)region
and
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
I didn't check if an error occurs into locationManager:didFailWithError:
At the moment I'm using the state to manually run two private methods that work as didEnter and didExit - in this case I'm also able to monitor the region but I didn't get why locationManager:didEnterRegion: and locationManager:didExitRegion: are never called.
Is someone facing the same behavior?
There are several items to check. The one that addressed my problem was Enabling Background App Refresh in your device's settings (see screenshot below). I had this disabled as a battery saving measure. Monitoring will not work if this is disabled.
If this doesn't address your problem there is a great post you can read that details all of the items to troubleshoot.
iBeacon StartMonitoringForRegion Doesn’t Work
This should work. I would like to see the rest of your code that sets up the monitoring, and I would put NSLog statements in your didEnterRegion didExitRegion and didDetermineState (log the state value, too).
It could be that iOS thinks no region transitions are occurring -- that you are always "in" the region, thus no transition. Transitions can take up to 15 min to occur in the background (although if you are ranging in the foreground it should be within 4 secs for an "out" and 1 sec for an "in". See http://developer.radiusnetworks.com/2013/11/13/ibeacon-monitoring-in-the-background-and-foreground.html
You can force an in/out region callback by setting region.notifyEntryStateOnDisplay=YES; on your monitored region, then hit the shoulder button. This should force monitoring callback. If you do this and don't see the log statements I suggested adding above, I would be very surprised.
I've tried almost everything and it didn't work.
Then I simply restarted my iPhone...and it started working. Incredible.
I had this problem with Estimote Beacons.

StartUpdateLocations in Background, didUpdatingToLocation only called 10-20 times

Testing Device: iPhone 5 (iOS 7)
I have an app that uses RegionMonitoring and updateLocation. If a region is entered, didEnterRegion is called as expected. Then I call startUpdatingLocation. But the method didUpdateToLocation is only called 10-20 times while it should update the location until the timer fires.
The relevant code:
CLLocationManager *_locationManager;
NSTimer *_timer;
-(void)initLocationManager
{
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
[_locationManager setActivityType:CLActivityTypeOther];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[_locationManager setPausesLocationUpdatesAutomatically:NO];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
}
//Did Enter Region, called as expected:
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
[_locationManager startUpdatingLocation];
_timer = [NSTimer scheduledTimerWithTimeInterval:300.0f target:self selector:#selector(scheduleMethod:) userInfo:nil repeats:NO];
}
//Timer Fire Method:
- (void) scheduleMethod:(NSTimer*)timer
{
[Utils writeToLog:#"Timer-Stop"];
[_locationManager stopUpdatingLocation];
}
//This Method only called 10-20 Times (in the first 10-20 Seconds) and not the complete 5 Minutes:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[Utils writeToLog:#"LocationUpdate!"];
}
So far I tried:
Restarting the Updates in the locationManagerDidPauseLocationUpdates method, but it seems that this is never be called:
-(void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager
{
[WRUtils writeToLog:#"LocationUpdate paused, restarted"];
[_locationManager startUpdatingLocation];
}
Check for errors in the didFailWithError method, but this is not called either.
And played a bit with the properties:
[_locationManager setActivityType:CLActivityTypeOther];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[_locationManager setPausesLocationUpdatesAutomatically:NO];
Plist settings are right I guess:
Required background modes YES
Required background Modes
Item 0 App registers for location updates
How can I solve this?
Apple has introduced a new policy in iOS 7. iOS 7 does no longer deliver location updates in the background if you call „startUpdatingLocation“ while the App is in the background. You only get update when the App is brought to the foreground in this case.
When you’re using the geofencing feature, your App just gets a few seconds each time you get a RegionEntered/Exited notification to process this notification. And in these few seconds you may also get location updates. After these few seconds are over iOS 7 just suspends your App again.
You can use background task to get more than just a few seconds, but in iOS 7 Apple has also reduced the time Apps can run in the background from 10 minutes (iOS 6 and older) to only 3 minutes under iOS 7. It looks like that these 3 minutes are the total amount for the whole time the App is in the background. Which means you can not ask iOS 7 10 times to get 1 minute background time, you’ll only get 3 minutes in total, so after the 3rd time you’ve asked for a minute, your App won't get any background time anymore at all.
Your only chance in getting location updates in the background is to call „startUpdatingLocation“ while the App is in the foreground. This is sad especially when you only need location updates in response to Region(Enter/Exit messages, because you need to let the location updates running all the time. But you can at least reduce the battery usage by setting the accuracy value to kCLLocationAccuracyThreeKilometers when
you do not need location updates and set the accuracy to kCLLocationAccuracyBest only when you really need the geo coordinates. The iOS won’t power up GPS for the kCLLocationAccuracyThreeKilometers value, so the battery usage would be moderate in this case.
Also the value kCLLocationAccuracyBestForNavigation for the accuracy seems to cause problems under IOS 7. I do not get any location updates with this value if the device is not connected to a an external power supply.
All in all the new iOS 7 policy for location updates is making it much harder to develop certain kinds of Apps. Instead of registering for location updates only when needed, you are forced to register for these for the while lifetime of your App. Which of course drains the battery a little bit faster, though Apple’s intension for this new policy was probably the opposite.
UPDATE:
After some more testing I’ve found some kind of solution for the problem.
The docs from Apple mention that when using the Significant Location Change API, Apps can receive location updates in the background even if „startUpdatingLocation“ is started in the background.
My first tests didn’t work well. I was registering my App for significant location updates within the region monitoring delegate methods just before calling startUpdatingLocation (so this location service is only enabled when needed), but this still does not deliver location updates in the background as the docs would suggest.
But if you start listening for significant location changes directly after your App is launched (and never switch this off), you can call start „startUpdatingLocation“ while the App is in the background and also receive location updates in the background. The battery usage of having the "significant location change“ feature on all the time seems to be very low, so this will be probably the solution for most Apps.
You have to check if the „significant location change“ feature is available on the device, but it seems that all current devices do support this. Even the 5th generation of iPod Touch does support it (The iPod Touch can not use cell towers for location updates, which is the base method of this feature according to the docs from Apple, so I guess we can assume that all current devices running iOS 7 can use the „significant location update“ API. Though it’s probably a good idea to check if this feature is really available, maybe there are certain circumstances where the feature is not available).
Using the "significant location change“ API might have one disadvantage: The App can be launched in the background (if it was terminated in the background by the iOS to reuse its memory for other Apps) repeatedly and unnecessarily whenever the device has moved „significantly“ (according to the docs: when the cell tower has changed, but no more than once per 5 min). So Apps which only need to be activated, when a certain region is exited or entered, will be launched and informed about location changed all the time, not only at those regions. But I assume this should be still much better than having standard location updates active all the time.
My iPhone 5s drains the battery only 1% over night with the significant location changes active, instead of 12% with having the standard location updates active with the accuracy set to 3km.
Hope this helps all developers who are struggling with the new iOS 7 behavior.
In background timer will not run, so here your timer object will not respond, You need to create background task handler, check comment of below link,
How to run the timer in background of the application?
In background if you want to continue location service than you need to set pausesLocationUpdatesAutomatically flag, flag info on
pausesLocationUpdatesAutomatically flag info
if ([self.locationManager respondsToSelector:#selector(pausesLocationUpdatesAutomatically)]) {
self.locationManager.pausesLocationUpdatesAutomatically = NO;
}
check my comment on
Location service going to "Inactive" state in iPhone 5
For location manager there below are the CLLocationManagerDelegate methods for location update,
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation [Deprecated in __IPHONE_6_0]
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);
Where you found
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation ??
Use below code in your didEnterRegion Method to start updates again
[_locationManager startMonitoringSignificantLocationChanges];
if ([_locationManager respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)])
{
_locationManager.allowsBackgroundLocationUpdates =YES;
}
[_locationManager startUpdatingLocation];

Resources