我在使用iOS和iBeacon时遇到了一个非常奇怪的错误.我有一个非常简单的BeaconManager,它使用特定的UUID,主要和次要值来定义信标,并在找到它们后执行一些操作.我的应用似乎正常工作,直到它不断切换蓝牙状态并停止工作.唯一可见的结果是状态栏中的蓝牙图标由于蓝牙停止和重新启动而开始闪烁.
在哪里集中注意力?
这是我的班级定义:
#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 (i.e. delivers a coupon) [self.delegate didFoundBeacon:self]; } self.locationManager = nil; } // else [self.locationManager stopMonitoringForRegion:region]; } [foundBeacons removeObjectAtIndex:0]; beacon = nil; } } @end
解决方法
不能肯定这是蓝牙不断切换的原因,但这部分肯定是可疑的:
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { [self.locationManager startMonitoringForRegion:beaconRegion]; [self.locationManager startRangingBeaconsInRegion:beaconRegion]; }
这基本上是一个无限循环.一旦监控开始,iOS就会调用didStartMonitoring方法……它开始监控同一个区域,这使得iOS再次调用didStartMonitoring方法,其中……