¿Por qué las balizas hacen que Bluetooth cambie continuamente?

Estoy experimentando un error realmente extraño trabajando con iOS y iBeacon. Tengo un BeaconManager realmente simple que BeaconManager balizas con UUID particulares, valores mayores y menores y realiza algunas acciones una vez que los encontró. Mi aplicación parece funcionar correctamente hasta que alterna continuamente el estado de Bluetooth y deja de hacer su trabajo. El único resultado visible es que el icono de Bluetooth en la barra de estado comienza a parpadear debido a la detención y reinicio de Bluetooth.

¿Dónde concentrar la atención?

Esta es mi definición de class:

 #import "BeaconManager.h" @implementation BeaconManager - (instancetype)init { self = [super init]; if (self) { NSURL *beep = [[NSBundle mainBundle] URLForResource:@"beep" withExtension:@"aiff"]; soundFileURLRef = (CFURLRef) CFBridgingRetain(beep); AudioServicesCreateSystemSoundID(soundFileURLRef, &soundFileObject); // Initializes properties beacon = [CLBeacon new]; foundBeacons = [NSMutableArray new]; _lastBeaconActionTimes = [[NSMutableDictionary alloc] init]; } return self; } - (void)initRegion { // Initializes the beacon region by giving it an UUID and an identifier NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:BEACON]; beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"beacon.region"]; // Starts looking for beacon within the region [self.locationManager startMonitoringForRegion:beaconRegion]; } - (void)checkBeacon { if (!self.locationManager) { self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) [self.locationManager requestWhenInUseAuthorization]; } [self initRegion]; [self locationManager:self.locationManager didStartMonitoringForRegion:beaconRegion]; } #pragma mark - CLLocationManagerDelegate - (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { [self.locationManager startMonitoringForRegion:beaconRegion]; [self.locationManager startRangingBeaconsInRegion:beaconRegion]; } - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { [self.locationManager startRangingBeaconsInRegion:beaconRegion]; } - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { [self.locationManager stopRangingBeaconsInRegion:beaconRegion]; } - (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error { NSLog(@"Failed monitoring region: %@", error); } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"Location manager failed: %@", error); } - (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region { if (foundBeacons.count == 0) { for (CLBeacon *filterBeacon in beacons) { // If a beacon is located near the device and its major value is equal to 1000 (MAJOR constant) if (((filterBeacon.proximity == CLProximityImmediate) || (filterBeacon.proximity == CLProximityNear))) // Registers the beacon to the list of found beacons [foundBeacons addObject:filterBeacon]; } } // Did some beacon get found? if (foundBeacons.count > 0) { // Takes first beacon of the list beacon = [foundBeacons firstObject]; if (([beacon.major isEqualToNumber:[NSNumber numberWithInt:MAJOR]]) && ([beacon.minor isEqualToNumber:[NSNumber numberWithInt:MINOR]])) { // Takes the actual date and time NSDate *now = [[NSDate alloc] init]; NSString *key = [NSString stringWithFormat:@"%@ %@ %@", [beacon.proximityUUID UUIDString], beacon.major, beacon.minor]; NSDate *lastBeaconActionTime = [_lastBeaconActionTimes objectForKey:key]; if ((lastBeaconActionTime == nil) || ([now timeIntervalSinceDate:lastBeaconActionTime] > MINIMUM_ACTION_INTERVAL_SECONDS)) { [_lastBeaconActionTimes setObject:now forKey:key]; // Plays beep sound AudioServicesPlaySystemSound(soundFileObject); if (self.delegate) { // Performs actions related to the beacon (ie delivers a coupon) [self.delegate didFoundBeacon:self]; } self.locationManager = nil; } // else [self.locationManager stopMonitoringForRegion:region]; } [foundBeacons removeObjectAtIndex:0]; beacon = nil; } } @end 

No puedo decir con certeza que esta es la razón por la que Bluetooth sigue alternando, pero esta parte es definitivamente sospechosa:

 - (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { [self.locationManager startMonitoringForRegion:beaconRegion]; [self.locationManager startRangingBeaconsInRegion:beaconRegion]; } 

Esto es esencialmente un bucle infinito. Una vez que se inicia la monitorización, iOS invoca el método didStartMonitoring … que comienza a monitorear en la misma región, lo que hace que el iOS invoque nuevamente el método didStartMonitoring , que …

Comenzaría por eliminar la línea startMonitoringForRegion de esta parte de su código.