iOS 开发 高德-----定位

单次定位

  • 初始化
@property (nonatomic, strong) AMapLocationManager *locationManager;
@property (nonatomic, copy) AMapLocatingCompletionBlock completionBlock;

//单次定位
    self.locationManager = [[AMapLocationManager alloc] init];
    
    [self.locationManager setDelegate:self];
    
    //设置期望定位精度
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyHundredMeters];
    
    //设置不允许系统暂停定位
    [self.locationManager setPausesLocationUpdatesAutomatically:NO];
    
    //设置允许在后台定位
    [self.locationManager setAllowsBackgroundLocationUpdates:YES];
    
    //设置定位超时时间
    [self.locationManager setLocationTimeout:DefaultLocationTimeout];
    
    //设置逆地理超时时间
    [self.locationManager setReGeocodeTimeout:DefaultReGeocodeTimeout];
    
    //设置开启虚拟定位风险监测,可以根据需要开启
    [self.locationManager setDetectRiskOfFakeLocation:NO];
    [self.mapView removeAnnotations:self.mapView.annotations];

    //进行单次带逆地理定位请求
       YES:返回带逆定理 返回坐标和地址信息
       No:不带逆地理定位请求
    [self initCompleteBlock];//  ps:需要在请求前调用
    [self.locationManager requestLocationWithReGeocode:NO completionBlock:self.completionBlock];
或
    [self.locationManager requestLocationWithReGeocode:YES   completionBlock:^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {

    }];
  • Block 回调(单次定位请求后Block回调)
//单次定位后的bolck回调
-(void)initCompleteBlock{
    self.completionBlock = ^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {
        NSLog(@"===%@",location);
        
        //带逆地理
        if (regeocode)
        {
          NSString * str =[NSString stringWithFormat:@"%@ \n %@-%@-%.2fm", regeocode.formattedAddress,regeocode.citycode, regeocode.adcode, location.horizontalAccuracy];
        }
        else
        {
           NSString * str  = [NSString stringWithFormat:@"lat:%f;lon:%f \n accuracy:%.2fm", location.coordinate.latitude, location.coordinate.longitude, location.horizontalAccuracy];
        }
    };
    
}

持续定位

  • 初始化
 self.locationManager = [[AMapLocationManager alloc] init];
    self.locationManager.delegate = self;
    //设置定位最小更新距离方法如下,单位米
    self.locationManager.distanceFilter = 200;
    //设置不允许系统暂停定位
    [self.locationManager setPausesLocationUpdatesAutomatically:NO];
     //设置允许在后台定位
    [self.locationManager setAllowsBackgroundLocationUpdates:YES];
    
    //开启持续定位
    [self.locationManager startUpdatingLocation];
    //持续定位返回逆地理编码信息
    [self.locationManager setLocatingWithReGeocode:YES];
  • 接收/处理位置更新
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location reGeocode:(AMapLocationReGeocode *)reGeocode
{
    NSLog(@"location:{lat:%f; lon:%f; accuracy:%f; reGeocode:%@}", location.coordinate.latitude, location.coordinate.longitude, location.horizontalAccuracy, reGeocode.formattedAddress);
    
//    //获取到定位信息,更新annotation
//    if (self.pointAnnotaiton == nil)
//    {
//        self.pointAnnotaiton = [[MAPointAnnotation alloc] init];
//        [self.pointAnnotaiton setCoordinate:location.coordinate];
//
//        [self.mapView addAnnotation:self.pointAnnotaiton];
//    }
//
//    [self.pointAnnotaiton setCoordinate:location.coordinate];
//
//    [self.mapView setCenterCoordinate:location.coordinate];
//    [self.mapView setZoomLevel:15.1 animated:NO];
}

方向定位

  • 开始定位
 //开始进行连续定位
    [self.locationManager startUpdatingLocation];

  // headingAvailable 设备是否支持方向识别
  YES:设备支持方向识别 ; NO:设备不支持支持方向识别
    if ([AMapLocationManager headingAvailable] == YES)
    {
        [self.locationManager startUpdatingHeading];
    }
  • 停止定位
     //停止定位
        [self.locationManager stopUpdatingLocation];
        [self.locationManager stopUpdatingHeading];
        
        //移除地图上的annotation
        [self.mapView removeAnnotations:self.mapView.annotations];
        self.pointAnnotaiton = nil;
        _annotationView = nil;
  • 回调(可用此修改方向之类的)
@property (nonatomic, assign) CGFloat annotationViewAngle;

/**
 *  @brief 设备方向改变时回调函数
 *  @param manager 定位 AMapLocationManager 类。
 *  @param newHeading 设备朝向。
 */
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
if (_annotationView != nil)
    {
        CGFloat angle = newHeading.trueHeading*M_PI/180.0f + M_PI - _annotationViewAngle;
        NSLog(@"################### heading : %f - %f", newHeading.trueHeading, newHeading.magneticHeading);
        _annotationViewAngle = newHeading.trueHeading*M_PI/180.0f + M_PI;
        _heading = newHeading;
        _annotationView.transform =  CGAffineTransformRotate(_annotationView.transform ,angle);
    }
}

后台定位

     //iOS 9(不包含iOS 9) 之前设置允许后台定位参数,保持不会被系统挂起
[self.locationManager setPausesLocationUpdatesAutomatically:NO];

//iOS 9(包含iOS 9)之后新特性:将允许出现这种场景,同一app中多个locationmanager:一些只能在前台定位,另一些可在后台定位,并可随时禁止其后台定位。
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
    self.locationManager.allowsBackgroundLocationUpdates = YES;
}

地理围栏

  • 旧版
//创建圆形地理围栏
    AMapLocationCircleRegion *cirRegion200 = [[AMapLocationCircleRegion alloc] initWithCenter:coordinate
                                                                                       radius:200.0
                                                                                   identifier:@"circleRegion200"];
    //添加地理围栏
    [self.locationManager startMonitoringForRegion:cirRegion200];
//添加地理围栏对应的Overlay,方便查看
    MACircle *circle200 = [MACircle   circleWithCenterCoordinate:coordinate radius:200.0];
   [self.mapView addOverlay:circle200];
    [self.mapView setVisibleMapRect: circle200.boundingMapRect];

停止地理围栏

[self.regions enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [self.locationManager stopMonitoringForRegion:(AMapLocationRegion *)obj];
    }];
  • 新版
    新版的高德地图对地理围栏进行了优化,把地理围栏从AMapLocationManager中剥离,有了自己单独的管理类AMapGeoFenceManager。当围栏创建完毕,且围栏创建成功时会启动定位,这部分无需您来设置,SDK内部执行。 定位机制:通过“远离围栏时逐渐降低定位频率”来降低电量消耗,“离近围栏时逐渐提高定位频率”来保证有足够的定位精度从而完成围栏位置检测。需要注意,在iOS9及之后版本的系统中,如果您希望程序在后台持续检测围栏触发行为,需要保证manager的allowsBackgroundLocationUpdates为YES,设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
    ------来自网络

初始化地理围栏manager

 self.geoFenceManager = [[AMapGeoFenceManager alloc] init];
    self.geoFenceManager.delegate = self;
    //需要进行通知的行为
    self.geoFenceManager.activeAction = AMapGeoFenceActiveActionInside | AMapGeoFenceActiveActionOutside | AMapGeoFenceActiveActionStayed; //进入,离开,停留都要进行通知
    self.geoFenceManager.allowsBackgroundLocationUpdates = YES;  //允许后台定位

添加围栏
圆形围栏

 CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(39.908692, 116.397477); //天安门
    if (self.userLocation) {
        coordinate = self.userLocation.coordinate;
    }
    [self.geoFenceManager addCircleRegionForMonitoringWithCenter:coordinate radius:300 customID:@"circle_1"];

多边形围栏

    NSInteger count = 4;
    CLLocationCoordinate2D *coorArr = malloc(sizeof(CLLocationCoordinate2D) * count);
    
    coorArr[0] = CLLocationCoordinate2DMake(39.933921, 116.372927);     
    coorArr[1] = CLLocationCoordinate2DMake(39.907261, 116.376532);     
    coorArr[2] = CLLocationCoordinate2DMake(39.900611, 116.418161);     
    coorArr[3] = CLLocationCoordinate2DMake(39.941949, 116.435497);     
    [self doClear];
    [self.geoFenceManager addPolygonRegionForMonitoringWithCoordinates:coorArr count:count customID:@"polygon_1"];

POI关键词围栏

[self.geoFenceManager addKeywordPOIRegionForMonitoringWithKeyword:@"北京大学" POIType:@"高等院校" city:@"成都" size:20 customID:@"poi_1"];

POI周边围栏

   CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(39.908692, 116.397477); //天安门
    [self.geoFenceManager addAroundPOIRegionForMonitoringWithLocationPoint:coordinate aroundRadius:10000 keyword:@"肯德基" POIType:@"050301" size:20 customID:@"poi_2"];

行政区域围栏

 [self.geoFenceManager addDistrictRegionForMonitoringWithDistrictName:@"成都市" customID:@"district_1"];

获取围栏创建后的回调

- (void)amapGeoFenceManager:(AMapGeoFenceManager *)manager didAddRegionForMonitoringFinished:(NSArray *)regions customID:(NSString *)customID error:(NSError *)error {
    if (error) {
        NSLog(@"创建失败 %@",error);
    } else {
        NSLog(@"创建成功");
    }
//添加地理围栏对应的Overlay,方便查看
以圆形围栏 为例
    if ([customID hasPrefix:@"circle"]) {
        if (error) {
            NSLog(@"======= circle error %@",error);
        } else {
            AMapGeoFenceCircleRegion *circleRegion = (AMapGeoFenceCircleRegion *)regions.firstObject;  //一次添加一个圆形围栏,只会返回一个
         MACircle *circleOverlay = [MACircle circleWithCenterCoordinate:coordinate radius:radius];
         [self.mapView addOverlay:circleOverlay];
         [self.mapView setVisibleMapRect:circleOverlay.boundingMapRect edgePadding:UIEdgeInsetsMake(20, 20, 20, 20) animated:YES];   //设置地图的可见范围,让地图缩放和平移到合适的位置
        }
}

围栏状态改变时的回调

- (void)amapGeoFenceManager:(AMapGeoFenceManager *)manager didGeoFencesStatusChangedForRegion:(AMapGeoFenceRegion *)region customID:(NSString *)customID error:(NSError *)error {
    if (error) {
        NSLog(@"status changed error %@",error);
    }else{
        NSLog(@"status changed success %@",[region description]);
    }
}

移除围栏

- (void)removeTheGeoFenceRegion:(AMapGeoFenceRegion *)region; //移除指定围栏
- (void)removeGeoFenceRegionsWithCustomID:(NSString *)customID; //移除指定customID的围栏
- (void)removeAllGeoFenceRegions;  //移除所有围栏

区域判断

//设置一个目标经纬度
CLLocationCoordinate2D coodinate = CLLocationCoordinate2DMake(39.948691, 116.492479);
//返回是否在大陆或以外地区,返回YES为大陆地区,NO为非大陆。
BOOL flag= AMapLocationDataAvailableForCoordinate(coodinate);

你可能感兴趣的:(iOS 开发 高德-----定位)