<p>
iOS 8 之后定位需要加字段在info.plst里面,NSLocationAlwaysUsageDescription 一直定位、NSLocationWhenInUseUsageDescription 使用时定位</p><p><span style="white-space: pre;"> </span>苹果目前允许beacon在后台一直搜寻,但是传统的定位会以损耗电池为由拒绝通过。(未验证beacon后台可以上线)</p><p><span style="white-space: pre;"> </span>定位的heading,即方向是不需要用户同意的,判断设备可用即可。</p><p><span style="white-space: pre;"> </span>接下来附demo</p>
#define myUUID @"AB8190D5-D11E-4941-ACC4-42F30510B408"
- (void)viewDidLoad {
[super viewDidLoad];
NSUUID *uuid = [[NSUUID alloc]initWithUUIDString:myUUID];
_myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"test"];
_myBeaconRegion.notifyOnEntry = YES;
_myBeaconRegion.notifyOnExit = YES;
_myBeaconRegion.notifyEntryStateOnDisplay = YES;
[self createLocationManager];
self.countryLabel.text = @"正在检测";
self.cityLabel.text = @"正在检测";
_mutArray = [NSMutableArray array];
}
#pragma mark - createLocationManager
-(void)createLocationManager{
_manager = [MyCLLocationManager sharedManager];
_manager.delegate = self;
_manager.desiredAccuracy = kCLLocationAccuracyKilometer;
//ignore filter default kCLDistanceFilterNone will report any change
_manager.distanceFilter = 500;
_bluetoothManager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];
//request device location available
if ([CLLocationManager locationServicesEnabled]) {
//request location available
int status = [CLLocationManager authorizationStatus];
//status == 0 neverSet
if (status == 0) {
[_manager requestAlwaysAuthorization];
}
if ([CLLocationManager headingAvailable]) {
[_manager startUpdatingHeading];
}else{
[_manager stopUpdatingHeading];
}
/*
status == 3 alwaysLocation
status == 4 WhenInUseLocation
*/
if (status >= 3) {
[_manager startRangingBeaconsInRegion:_myBeaconRegion];
_myGeocoder = [[CLGeocoder alloc]init];
}else{
[_manager stopUpdatingLocation];
}
}
}
#pragma mark - CLLocationDelegate
//start Location
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
// CLGeocoder
CLLocation *currentLocation = [locations lastObject];
if (currentLocation.horizontalAccuracy > 0) {
float longitude = currentLocation.coordinate.longitude;
float latitude = currentLocation.coordinate.latitude;
NSString *longitudeStr = [NSString stringWithFormat:@"东经%.2f",currentLocation.coordinate.longitude];
NSString *latitudeStr = [NSString stringWithFormat:@"北纬%.2f",currentLocation.coordinate.latitude];
if (!longitude > 0) {
longitudeStr = [NSString stringWithFormat:@"西经%.2f",currentLocation.coordinate.longitude];
}
if (!latitude > 0) {
latitudeStr = [NSString stringWithFormat:@"南纬%.2f",currentLocation.coordinate.latitude];
}
[self reverseGeocodeLocation:currentLocation];
}
if (currentLocation.verticalAccuracy > 0) {
NSString *elevationStr = [NSString stringWithFormat:@"海拔%.1f米",currentLocation.altitude];
}
}
//start heading
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
if (newHeading.headingAccuracy >= 0) {
float magneticHeading = newHeading.magneticHeading;
NSString *direction = [NSString string];
if (magneticHeading < 90) {
direction = @"北";
}else if (magneticHeading > 90 && magneticHeading < 180){
direction = @"东";
magneticHeading = magneticHeading - 90;
}else if (magneticHeading > 180 && magneticHeading < 270){
direction = @"南";
}else if (magneticHeading > 270){
direction = @"西";
magneticHeading = magneticHeading - 270;
}
}
}
//
-(BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager{
return NO ;
}
#pragma mark - CLGeocoder
-(void)reverseGeocodeLocation:(CLLocation *)CLLocation{
[_myGeocoder reverseGeocodeLocation:CLLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (error == nil && [placemarks count] > 0) {
CLPlacemark *placekmark = [placemarks objectAtIndex:0];
// NSLog(@"%@",placekmark);
self.countryLabel.text = placekmark.locality;
self.cityLabel.text = placekmark.subLocality;
self.nameLabel.text = placekmark.name;
}
else if(error == nil && [placemarks count] == 0){
NSLog(@"No resulte were returned");
}
else if(error != nil){
NSLog(@"error:%@",error);
}
}];
}
#pragma mark - CLLocationStatus
//changeStatus
-(void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
if (status >= 3) {
[_manager startUpdatingLocation];
[_manager startMonitoringForRegion:_myBeaconRegion];
}else{
//兼容ios8以下
// UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"打开定位" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
// [alertView show];
[_manager stopUpdatingLocation];
}
NSLog(@"%d",status);
}
#pragma mark - beaconDelegate
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
NSLog(@"\nEnter BeaconRegion\n");
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region{
NSMutableArray *array = [NSMutableArray array];
for (CLBeacon *item in beacons) {
BeaconItem *oneItem = [[BeaconItem alloc]init];
oneItem.uuid = [NSString stringWithFormat:@"%@",item.proximityUUID];
oneItem.major = [item.major stringValue];
oneItem.minor = [item.minor stringValue];
oneItem.rssi = item.rssi;
[array addObject:oneItem];
}
_mutArray = array;
// [self registerLocalNotification];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
NSLog(@"\nExit BeaconRegion\n");
}
//failLocation
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(@"%@",error);
}
#pragma mark - bluetoothManagerDelegate
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
switch (peripheral.state) {
case CBPeripheralManagerStatePoweredOn:
{
NSLog(@"蓝牙打开可用");
}
break;
case CBPeripheralManagerStatePoweredOff:
NSLog(@"蓝牙关闭");
break;
default:
NSLog(@"蓝牙不可用");
break;
}
}
#pragma mark - memoryWarning
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
有一些属性是在storyboard上创建的label拖过来的,没有意义,可以打印替换。