I am trying to use location monitoring in my app. I can set my location and reverseGeocode the location I want to monitor. the didUpdateToLocation delegate method works fine, and updates continuously but the didStartMonitoingForRegion delegate never gets called, nor do the didExitRegion nor didEnterRegion.
Any suggestions?
- (IBAction)setLocation:(UIButton *)sender {
if(!self.locationManager) self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:10]; // Update again when a user moves distance in meters
[self.locationManager setPurpose:#"Set location based alerts if switch is on"];
self.plugLocation=nil; //reset to nil so didUpdateToLocation will update it
self.distanceLabel.text=[NSString stringWithFormat:#"%d",0];
[self.locationManager startUpdatingLocation];
if ( ![CLLocationManager regionMonitoringAvailable] || ![CLLocationManager regionMonitoringEnabled] ){
NSLog(#"Location monitoring not Unavailable");
}else {
}
}
-(void)setPlugLocation:(CLLocation *)plugLocation{
//
if (!_plugLocation) _plugLocation=[[CLLocation alloc]init];
_plugLocation=plugLocation;
if (_plugLocation) {
[self setRegion:plugLocation radius:20 name:self.plugName];
[self reverseGeocode:self.plugLocation];
NSLog(#"setPlugLocation %#", [self.plugLocation description]);
}
}
-(void)setRegion:(CLLocation *)center radius:(double)meters name:(NSString*)name{
CLLocationCoordinate2D plug2D;
plug2D.latitude=center.coordinate.latitude;
plug2D.longitude=center.coordinate.longitude;
CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:plug2D radius:meters identifier:name];
[self.locationManager startMonitoringForRegion:region desiredAccuracy:kCLLocationAccuracyBest];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
self.latitudeLabel.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.latitude];
self.longitudeLabel.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.longitude];
if (self.plugLocation == nil)self.plugLocation = newLocation;
if (self.plugLocation!=nil) {
CLLocationDistance distanceBetween = [newLocation distanceFromLocation:self.plugLocation];
NSLog(#"didUpdateToLocation Distance from plug=%f",distanceBetween);
self.distanceLabel.text=[NSString stringWithFormat:#"%f",distanceBetween];
}
}
-(void)reverseGeocode:(CLLocation *)coordinates;{
if (!self.plugGeo) self.plugGeo = [[CLGeocoder alloc] init];
[self.plugGeo reverseGeocodeLocation:coordinates completionHandler:^(NSArray *placemarks, NSError *error) {
if (error==nil&&[placemarks count]>0) {
CLPlacemark *placemark=[placemarks objectAtIndex:0];
NSLog(#" setPlugLocation geocodeAddressString %#",placemark);
//should also transfer back to plug detail and save
self.locationLabel.text=[NSString stringWithFormat:#"%# %#\n%#, %#", placemark.subThoroughfare, placemark.thoroughfare, placemark.locality,placemark.postalCode];
[self sendAlertMessage:[NSString stringWithFormat:#"%# %#\n%#, %#", placemark.subThoroughfare, placemark.thoroughfare, placemark.locality,placemark.postalCode] title:#"Success"];
}else {
NSLog(#" setPlugLocation couldn't geoCode address %#",error);
}
}];
}
Are you using the simulator to test your application? Something that I've found is that the simulator is completely unreliable for region exit/enters. Try compiling the project on your device by plugging it in and changing from iPhone Simulator to your iOS device. You can then unplug your device and run your app from your phone to test it.
Why doesn't the simulator work for regions? Regions are mostly determined by Apple's hidden algorithm using Wi-Fi, cell towers, and other applications on the phone requesting location. Seeing as a simulator doesn't use Wi-Fi or cell towers... region monitoring is going to be pretty impossible.
It's likely your code is fine (I see no glaring errors), but the simulator is giving you bad results. Try it on your device and let us know if it does the same thing.
Related
So it works when I'm on WiFi. But on 4G, it only works if I had been on Wifi and it already has the location. A lot of times without WiFi, the phone will say it's using my location but its not updating the label nor is it uploading the coordinates to the server. Here's the code:
- (void)viewDidLoad {
[super viewDidLoad];
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([self->locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self->locationManager requestWhenInUseAuthorization];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
CLLocation *newLocation = [locations lastObject];
NSString *locationLat = [NSString stringWithFormat:#"%.8f", newLocation.coordinate.latitude];
NSString *locationLong = [NSString stringWithFormat:#"%.8f", newLocation.coordinate.longitude];
latLongLabel.text = [NSString stringWithFormat:#"Lat: %# - Long%#",locationLat,locationLong];
[self postLocation:locationLat secondArg:locationLong];
}
- (void)postLocation: (NSString *)latitudeString secondArg:(NSString *)longitudeString {
//POST COORDINATES TO MY SERVER
}
- (IBAction)startUpdating:(id)sender {
[locationManager startUpdatingLocation];
}
My suspicion is that when you are on 4G, the location updates still work fine (although wifi triangulation makes them a bit more precise but only Apple knows how, as the implementation is private), BUT there might be an issue sending those values to the server quickly or reliably enough via 4G connection. (for example in London it is slow as hell with so many people around)
You might narrow the debugging by simply logging the location update directly to some UIlabel on your view, and not going through server infrastructure.
AS a last resort I would make sure
that you set your CLActivityType property to CLActivityTypeFitness
and pausesLocationUpdatesAutomatically is set to NO.
I've just updated to Xcode 6/iOS 8 SDK and my location service simulation in simulator started not working. It was fine before I updated (I'm currently unable to test on real device). Now, when I select a location for simulation, nothing happens. Delegate's -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations method is not called. I've restarted Xcode, cleaned the build folder, nothing changed. Why can this happen?
Since IOS 8 you need to ask for authorization before starting the CLLocationManager.
Are you calling one of these methods?
[self.locationManager requestWhenInUseAuthorization]; // For foreground access
[self.locationManager requestAlwaysAuthorization]; // For background access
If you have created the project before XCode 6, you probably also need to add the info.plist entry for the new permission.
For more details have a look at this post: Location Services not working in iOS 8
Add Below code in your method
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
Also add Below line at your info.plist file
Key:NSLocationWhenInUseUsageDescription value:Uses current location
Using Xcode 6.3.1 I have had the location selection stop updating. The fix was to run another project, select "Simulate location > Don't Simulate Location" then build the original project again to resume normal location setting.
- (void)startLocationUpdates{
geocoder = [[CLGeocoder alloc] init];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[locationManager requestWhenInUseAuthorization];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
}
// Reverse Geocoding
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
fullAddress = [NSString stringWithFormat:#"%#,%#,%#,%#",
placemark.thoroughfare,
placemark.locality,
placemark.administrativeArea,
placemark.country];
subtitleLocation = [NSString stringWithFormat:#"PostalCode::%#",
placemark.postalCode];
} else {
// NSLog(#"%#", error.debugDescription);
}
} ];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error{
NSLog(#"Cannot find the location.");
}
The other answers are correct, but I also had to reset the simulator before I could get a location, whereas it was working fine on a device. The app was initially installed on that simulator before iOS 8.
To reset your simulator :
https://stackoverflow.com/a/16195931
I am writing both Android and iOS apps which need to find BLE beacons around the device.
When I run my code from Android, it finds several beacons in the room I am in.
I have 8 beacons.
When I run the beacon code from iPhone, it returns a list of exactly 0 beacons.
Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self initRegion];
[self locationManager:self.locationManager didStartMonitoringForRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
- (void)initRegion {
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:BEACONUUID];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:BEACONIDENTIFIER];
[self.locationManager startMonitoringForRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(#"Beacon Found");
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(#"Left Region");
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
self.beaconFoundLabel.text = #"No";
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
CLBeacon *beacon = [beacons lastObject];//<== is always 0
self.beaconFoundLabel.text = #"Yes";
self.proximityUUIDLabel.text = beacon.proximityUUID.UUIDString;
self.majorLabel.text = [NSString stringWithFormat:#"%#", beacon.major];
self.minorLabel.text = [NSString stringWithFormat:#"%#", beacon.minor];
self.accuracyLabel.text = [NSString stringWithFormat:#"%f", beacon.accuracy];
if (beacon.proximity == CLProximityUnknown) {
self.distanceLabel.text = #"Unknown Proximity";
} else if (beacon.proximity == CLProximityImmediate) {
self.distanceLabel.text = #"Immediate";
} else if (beacon.proximity == CLProximityNear) {
self.distanceLabel.text = #"Near";
} else if (beacon.proximity == CLProximityFar) {
self.distanceLabel.text = #"Far";
}
self.rssiLabel.text = [NSString stringWithFormat:#"%ld", (long)beacon.rssi];
}
In my didRangeBeaconsInRegion, the beacons NSArray always comes up with 0 objects.
Though I have 8 objects. And i've downloaded several apps that are not mine, and they all see several of my beacons.
Why doesn't my code see any of my beacons?
Here is what I do whenever I'm setting up an iBeacon app.
Not all these things are necessary, but it will
work
keep your user happy
(maybe most importantly) keep Apple happy
iOS 8+ Only
First things first: if you're using iOS 8, you need to make sure you actually have access before using CLLocationManager.
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
// You can either use requestAlwaysAuthorization, or requestWhenInUseAuthorization
[self.locationManager requestAlwaysAuthorization];
You'll also need an entry for NSLocationAlwaysUsageDescription in your plist (again, iOS 8 only )
iOS 7+
Your App's pList
Regardless you're using iOS 8 or 7, you should add the following to your plist file (you need to decide if you'll use background or not).
Note: The below is in the form of KEY : KEY TYPE : VALUE for string, and KEY : KEY TYPE : [ Value1, Value2... ] for Arrays:
NSLocationUsageDescription : String : "Gimmie access to your location or else..."
NSBluetoothPeripheralUsageDescription : String : "Gimmie access to your blue tooth or else"
// Optionally supply if you need background modes. I don't believe you need this either if you plan to turn these options on using the Capabilities section of your App's Settings (see below section)
UIBackgroundModes : Array : [ location, bluetooth-central ]
UIApplicationExitsOnSuspend : Boolean : NO
Your App's Project Settings (Capabilities)
this section has been removed as this can cause your app to be rejected (as noted by #heypiotr in the comments)
Final Thoughts
A final suggestion would be to try moving [self locationManager:self.locationManager didStartMonitoringForRegion:self.beaconRegion] into your viewDidAppear.
Here is an example of what I typically do ( which works quite well for me ).
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self initLocationManager];
[self initBeaconRegion];
[self startMonitoring];
}
-(void)initLocationManager {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Not necessary, but I like to do it.
if( ![CLLocationManager locationServicesEnabled] ) {
[self.locationManager startUpdatingLocation];
}
// Only necessary if you're in iOS 8. Checking for existence though to support iOS 7
if( ![CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized ) {
if ([CLLocationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager performSelector:#selector( requestAlwaysAuthorization )];
}
}
}
-(void)initBeaconRegion {
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:kYOUR_UUID_HERE];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:kYOUR_IDENTIFIER_HERE];
// Change this to whatever you want....
self.beaconRegion.notifyEntryStateOnDisplay = YES;
self.beaconRegion.notifyOnEntry = NO;
self.beaconRegion.notifyOnExit = YES;
}
# pragma mark -
# pragma mark Monitoring Beacons
# pragma mark -
-(void)startMonitoring {
// Monitor Beacon signals around me and report them back to me
[self.locationManager startMonitoringForRegion:self.beaconRegion];
}
The last part ( placement in viewDidAppear ) may or may not help - it all depends I guess on too many factors to consider in a stackoverflow response.
Hope that helps and good luck!
Final Edit
Forgot one more thing that may help. There are some helpful methods that you can implement that can help you debug the issue further. Here is an example of a few of them:
#pragma mark Authorization Status Changed
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if( ![CLLocationManager locationServicesEnabled] ) {
NSLog(#"Couldn't turn on ranging: Location services are not enabled.");
} else {
NSLog(#"Location services ARE enabled.");
}
if( [CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized ) {
NSLog(#"Couldn't turn on monitoring: Location services not authorized.");
} else {
NSLog(#"Location services ARE authorized.");
}
}
#pragma mark -
#pragma mark CLLocationManager Errors
#pragma mark -
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog( #"FAIL ERROR: %#", [error description] );
}
-(void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion (CLBeaconRegion *)region withError:(NSError *)error {
NSLog( #"RANGE BEACONS ERROR: %#", [error description] );
}
First check with the other app like.Locate app add your UDID and check this app is showing your iBeacon. if not then there is a problem with apple IOS sometimes. then remove the app. Restart the app. it will work for you.
We had similar problem before, make sure your iBeacon device respond the scan request from iOS with a response DOES not contain manufacturer specific field.
Please check this note from apple
Before attempting to monitor any regions, your app should check whether region monitoring is supported on the current device. Here are some reasons why region monitoring might not be available:
The device doesn’t have the necessary hardware to support region
monitoring.
The user denied the app the authorization to use region monitoring.
The user disabled location services in the Settings app.
The user disabled Background App Refresh in the Settings app, either for the device or for your app.
5.The device is in Airplane mode and can’t power up the necessary hardware.
In iOS 7.0 and later, always call the isMonitoringAvailableForClass: and authorizationStatus class methods of CLLocationManager before attempting to monitor regions. (In OS X v10.8 and later and in previous versions of iOS, use the regionMonitoringAvailable class instead.) The isMonitoringAvailableForClass: method tells you whether the underlying hardware supports region monitoring for the specified class at all. If that method returns NO, your app can’t use region monitoring on the device. If it returns YES, call the authorizationStatus method to determine whether the app is currently authorized to use location services. If the authorization status is kCLAuthorizationStatusAuthorized, your app can receive boundary crossing notifications for any regions it registered. If the authorization status is set to any other value, the app doesn’t receive those notifications.
Apple link goes here
When I launch my application on my device, while being connected to Xcode, it works perfectly.
When I launch it again after removing it from the multitask, on the iPhone, (so without clicking the run button on Xcode), it doesn't work well anymore.
What works is :
In my viewDidLoad, I call [self retrieveData];
Here is retrieveData method : It is getting data from web :
It works perfectly when connected to Xcode and when not.
But when I launch the app from the iPhone without launching it from the Run button on Xcode's interface, then the locationManager: didUpdateTolocation method is not called properly because my application doesn't behave properly.
Additional informations for better understanding :
On iPhone Simulator the pop up shows. On iOS device while being launched from Xcode the pop up shows. I don't know why when I launch from the iPhone without Xcode and the cable the pop up doesn't show and I guess the didUpdateToLocation doesn't work properly. Any idea ?
Edited post reference to comment :
#pragma mark - Update Location
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = newLocation;
NSLog(#"didUpdateToLocation: %#", newLocation);
if (currentLocation != nil) {
// On affiche la longitude et latitude
longitudeLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
latitudeLabel.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
CLLocation *userLocation = [[CLLocation alloc] initWithLatitude:currentLocation.coordinate.latitude longitude:currentLocation.coordinate.longitude];
float distance = [userLocation distanceFromLocation:locDatabase];
NSLog(#"la distance est de : %f", distance);
if(distance<0.03)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Joleju" message:#"Vous entrez dans la zone!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
// ---------------------------------------------------------------------------------------------------------------------------
// Reverse Geocoding
NSLog(#"Resolving the Address");
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
adressLabel.text = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country];
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
}
}
Is this being called in viewDidLoad of your Main/Root/MasterViewController? (The one that is launched from your AppDelegate). If so, this method will only be called when the app first launches, not when it resumes from background. As an experiment, move the method call [self retrieveData] to viewWillAppear:
Edited Answer from more information: It's possible that your alert view show method is being called from a background thread and while you're in debug mode, it's still working, but as soon as you launch without the debugger, it's getting lost. UI methods should always be called from the main thread, so put a break point on the [alert show] line and see what thread it is using. To fix it, change the line to [alert performSelectorOnMainThread:#selector(show)]. I hope this finally solves your problem.
I identified a strange behaviour on my app using CoreLocation. I'm using the region monitoring functionality but, after authorising the location services (via popup or settings->Location Services) region monitoring fails (The operation couldn’t be completed. kCLErrorDomain error 5.). If I close the app and restart (therefore already authorised) everything works as expected.
My code looks like this:
-(void)initializeLocationServices
{
NSLog(#"Started location services");
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.pausesLocationUpdatesAutomatically = NO;
[locationManager startUpdatingLocation]; // to show authorisation popup
}
-(CLCircularRegion*)createRegion
{
// Test coordinates
CLLocationDegrees latitude = 50;
CLLocationDegrees longitude = -1;
CLLocationDistance radius = 50; // meters;
// If radius is too large, registration fails automatically, so limit the radius to the maximum value
if (radius > locationManager.maximumRegionMonitoringDistance) {
radius = locationManager.maximumRegionMonitoringDistance;
}
CLCircularRegion* region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(latitude, longitude) radius:radius identifier:#"TEST"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
NSLog(#"Created region");
return region;
}
-(void)monitorProximity
{
CLRegion *region = [self createRegion];
// Check if support is unavailable
if ( ![CLLocationManager isMonitoringAvailableForClass:[CLRegion class]]) {
NSLog( #"Failed to initialise region monitoring: support unavailable");
return;
}
// Check if authorised
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) {
NSLog( #"Failed to initialise region monitoring: app not authorized to use location services");
return;
} else {
NSLog(#"Started monitoring proximity");
}
// Clear out any old regions to prevent buildup.
if ([locationManager.monitoredRegions count] > 0) {
for (id obj in locationManager.monitoredRegions)
[locationManager stopMonitoringForRegion:obj];
}
[locationManager startMonitoringForRegion:region];
}
-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
NSLog(#"Started monitoring for region: %#", [region description]);
[locationManager requestStateForRegion:region]; // check if already inside region
}
-(void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
NSLog(#"Failed to start monitoring for region: %#", [error localizedDescription]);
}
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
NSLog(#"didDetermineState");
if (state == CLRegionStateInside) {
NSLog(#"inside");
return;
} else if (state == CLRegionStateOutside) {
NSLog(#"outside");
} else {
NSLog(#"unknown");
}
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(#"didEnterRegion");
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(#"didExitRegion");
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
NSLog(#"Monitoring authorisation status is now: %#", status == kCLAuthorizationStatusAuthorized ? #"authorized" : #"not authorized");
if (status == kCLAuthorizationStatusAuthorized) {
[self monitorProximity];
}
}
Am I doing something wrong here? Do I have problems with the flow after didChangeAuthorizationStatus gets called?
From other user reports, it seems that kCLErrorDomain 5 is a 'catch all' for region monitoring fails; it doesn't provide much useful information. I believe that your issue is being caused by the line
[locationManager requestStateForRegion:region]; // check if already inside region
which you're calling from inside the delegate method didStartMonitoringForRegion:
I saw something very similar in my own project and taking this line out (or delaying its execution for a while) solved the issue. My best guess is that iOS is still doing running some internal region monitoring code when this delegate method fires, so it's not an appropriate time to call requestStateForRegion:
Try taking this out and see if it is the answer.
kCLErrorDomain code/error 5 means that you have tried to monitor more than 20 CLRegions.
Descriptio here
see startMonitoringForRegion description It says:
An app can register up to 20 regions at a time. In order to report region changes in a timely manner, the region monitoring service requires network connectivity.
kCLErrorDomain 5 is a catch all that can mean many different things.
One of the sources is when you call [locationManager requestStateForRegion:region] which is necessary when you first monitor for a region to know if you're already in the region or not. This is because the didEnter region will only be called when you actually enter the region. Usually this means the first time you monitor for the region, you must wait 5 seconds until the region is not detected, and only then will didEnter region fire off the next time you're in the region.
There are many different reports of causes to the problem:
Ensure no more than 20 beacons are being monitored
5 means "regionMonitoringFailure". Ensure the radius is not too large (not relevant for beacon monitoring).
Ensure location updates are registered
Omit calling requestStateForRegion, however I described above why it's necessary to do so.
Restarting device and bluetooth may help
Try with 30 second delay
None of these worked for me, however. I think my root cause was similar to the iOS 7.1 bug where it just randomly stopped working on some devices. I tried the restart and restart of bluetooth, nothing helped.
Not sure what changed, but I just tried again the next day and it started working.
Basically you may want to try a different device until this one starts working again.