I've simplified the question a bit. When I create and add regions in my app and interrogate the state of those regions I see the following in monitoringDidFailForRegion
method:
The operation couldn’t be completed. (kCLErrorDomain error 4.)
Checking the CLErrorDomain constants I see that error 4 is kCLErrorRegionMonitoringDenied
and it is described like so:
Access to the region monitoring service was denied by the user.
How is this possible? Here's my set up and what I've checked:
didChangeAuthorizationStatus
reports the correct status: kCLAuthorizationStatusAuthorized
didStartMonitoringForRegion
.What am I missing? Why do I see this error when Location Services are clearly enabled?
The object that you use to start and stop the delivery of location-related events to your app.
Monitoring Beacon Regions. Beacon region monitoring uses an iOS device's onboard radio to detect when the user is in the vicinity of Bluetooth low-energy devices that are advertising iBeacon information.
Core Location provides services that determine a device's geographic location, altitude, and orientation, or its position relative to a nearby iBeacon device. The framework gathers data using all available components on the device, including the Wi-Fi, GPS, Bluetooth, magnetometer, barometer, and cellular hardware.
So, I took yet another look at the documentation on Region Monitoring and I noticed this in the highlighted item in the list:
Determining the Availability of Region Monitoring
Before attempting to monitor any regions, your app should check to see if region monitoring is supported on the current device. There are several reasons why region monitoring might not be available:
- The device may not have the hardware needed to support region monitoring.
- The user might have denied the app the authorization to use region monitoring.
- The user may have disabled location services in the Settings app.
- The user may have disabled Background App Refresh in the Settings app, either for the device or for your app.
- The device might be in Airplane mode and unable to power up the necessary hardware.
Then I checked that Background App Refresh (a new feature at iOS 7: Settings > General > Background App Refresh) is turned on and available for my app. It was not. I turned the feature on and BOOM my regions are reporting their state now.
It is confusing and misleading that:
[CLLocationManager isMonitoringAvailableForClass:[CLRegion class]] returns YES
...even when Background App Refresh is disabled. I would think it would return NO.
UPDATE:
I have sent a bug report to Apple and added an Open Radar for this issue.
UPDATE 3-11-14:
Apple has confirmed that this is a bug.
In order to do region monitoring (at least in iOS 9) you need to request "always" authorization. This not documented anywhere I could find, but it's the only way I was able to get region monitoring working.
rdar://23566600 - if you're inside apple :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With