单次定位
- 初始化
@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);