// // MapManager.m // jiaPei // // Created by 张嵘 on 2018/9/20. // Copyright © 2018年 JCZ. All rights reserved. // #import "MapManager.h" static MapManager *manger = nil; static dispatch_once_t onceToken; //复用annotationView的指定唯一标识 static NSString *annotationViewIdentifier = @"com.Baidu.BMKPointAnnotation"; @interface MapManager () @property (nonatomic, strong) BMKMapManager *mapManager; //主引擎类 @property (nonatomic, strong) BMKLocationManager *locationManager; //定位对象 @property (nonatomic, strong) BMKUserLocation *userLocation;//当前位置对象 @property (nonatomic, assign) BOOL locationLock;//单次定位锁 @property (nonatomic, strong) LocCompletedBlock locCompletedBlock;//定位回调 @property (nonatomic, strong) BMKMapView *mapView;//地图View类 @property (nonatomic, assign) CGSize mapSize;//地图大小 @property (nonatomic, strong) BMKGeoCodeSearch *searcher;//搜索对象 @property (nonatomic, strong) SearchCompletedBlock searchCompletedBlock;//搜索回调 @property (nonatomic, strong) ReverseCompletedBlock reverseCompletedBlock;//反地理编码回调 @end @implementation MapManager + (MapManager *)sharedManager { dispatch_once(&onceToken, ^{ manger = [[self alloc] init]; }); return manger; } - (instancetype)init { self = [super init]; if (self) { // 初始化定位SDK [[BMKLocationAuth sharedInstance] checkPermisionWithKey:BAIDU_APPKEY authDelegate:self]; // ‼️重要:设置用户是否同意SDK隐私协议,请务必在BMKLocationManager和BMKGeoFenceManager实例化之前调用,否则实例化失败 [[BMKLocationAuth sharedInstance] setAgreePrivacy:YES]; //要使用百度地图,请先启动BMKMapManager _mapManager = [[BMKMapManager alloc] init]; /** 百度地图SDK所有API均支持百度坐标(BD09)和国测局坐标(GCJ02),用此方法设置您使用的坐标类型. 默认是BD09(BMK_COORDTYPE_BD09LL)坐标. 如果需要使用GCJ02坐标,需要设置CoordinateType为:BMK_COORDTYPE_COMMON. */ if ([BMKMapManager setCoordinateTypeUsedInBaiduMapSDK:BMK_COORDTYPE_BD09LL]) { NSLog(@"经纬度类型设置成功"); } else { NSLog(@"经纬度类型设置失败"); } //启动引擎并设置AK并设置delegate BOOL result = [_mapManager start:BAIDU_APPKEY generalDelegate:self]; if (!result) { NSLog(@"启动引擎失败"); } } return self; } - (void)dealloc { _mapView.delegate = nil; } #pragma mark - Custom Way /** 根据大小创建地图 @param size 大小 @return 返回地图 */ - (BMKMapView *)getMapViewWithSize:(CGSize)size { _mapSize = size; return self.mapView; } /** 单次定位 @param completeBlock 定位回调 */ - (void)updateLocationWithCompleteBlock:(LocCompletedBlock)completeBlock { @weakify(self) self.locationLock = YES; self.locationManager.distanceFilter = kCLDistanceFilterNone; [self.locationManager requestLocationWithReGeocode:YES withNetworkState:YES completionBlock:^(BMKLocation * _Nullable location, BMKLocationNetworkState state, NSError * _Nullable error) { @strongify(self) if (location != nil) { self.locationLock = NO; if (completeBlock) { completeBlock(location != nil , location.location); } } if (error) [self showErrorAlertWithError:error]; }]; } /** 连续定位 @param distanceFilter 设定定位的最小更新距离。默认为 kCLDistanceFilterNone @param completeBlock 定位回调 */ - (void)updateLocationWithDistanceFilter:(NSInteger)distanceFilter CompleteBlock:(LocCompletedBlock)completeBlock { [self.locationManager startUpdatingLocation]; self.locationManager.distanceFilter = distanceFilter? distanceFilter : kCLDistanceFilterNone; _locCompletedBlock = completeBlock; } /** 返回地址信息搜索结果 @param address 地址(必填) @param city 城市(选填) @param completeBlock 搜索回调 */ - (void)onGetGeoCodeWithAddress:(NSString *)address City:(NSString *)city completeBlock:(SearchCompletedBlock)completeBlock { BMKGeoCodeSearchOption *geoCodeSearchOption = [[BMKGeoCodeSearchOption alloc]init]; geoCodeSearchOption.city= city; geoCodeSearchOption.address = address; [self.searcher geoCode:geoCodeSearchOption]; _searchCompletedBlock = completeBlock; } /** 返回反地理编码搜索结果 @param location 定位 @param completeBlock 搜索回调 */ - (void)onGetReverseGeoCodeWithLocation:(CLLocation *)location completeBlock:(ReverseCompletedBlock)completeBlock { BMKReverseGeoCodeSearchOption *reverseGeoCodeSearchOption = [[BMKReverseGeoCodeSearchOption alloc]init]; reverseGeoCodeSearchOption.location = location.coordinate; [self.searcher reverseGeoCode:reverseGeoCodeSearchOption]; _reverseCompletedBlock = completeBlock; } /** 错误弹窗 */ - (void)showErrorAlertWithError:(NSError *)error { switch (error.code) { case BMKLocationErrorDenied: { UIAlertView *alert =[[UIAlertView alloc]initWithTitle:@"温馨提示" message:@"请在iPhone的“设置”-“隐私”-“定位服务”功能中,找到“优易学车”打开位置访问权限" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil]; [alert show]; } break; default: break; } [_locationManager stopUpdatingLocation]; } /** 开始定位 */ - (void)beginLocation{ [self.locationManager startUpdatingLocation]; [self.locationManager startUpdatingHeading]; } #pragma mark - BMKLocationAuthDelegate 定位鉴权代理 /** * @brief 返回授权验证错误 * @param iError 错误号 : 为0时验证通过,具体参加BMKLocationAuthErrorCode */ - (void)onCheckPermissionState:(BMKLocationAuthErrorCode)iError { switch (iError) { case BMKLocationAuthErrorUnknown: NSLog(@"未知错误"); break; case BMKLocationAuthErrorSuccess: NSLog(@"鉴权成功"); break; case BMKLocationAuthErrorNetworkFailed: NSLog(@"因网络鉴权失败"); break; case BMKLocationAuthErrorFailed: NSLog(@"KEY非法鉴权失败"); break; default: break; } } /** 联网结果回调 @param iError 联网结果错误码信息,0代表联网成功 */ - (void)onGetNetworkState:(int)iError { if (0 == iError) { NSLog(@"联网成功"); } else { NSLog(@"联网失败:%d", iError); } } #pragma mark - BMKMapViewDelegate 地图代理 #pragma mark - BMKGeoCodeSearchDelegate 搜索代理 - (void)onGetGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKGeoCodeSearchResult *)result errorCode:(BMKSearchErrorCode)error { if (_searchCompletedBlock) { _searchCompletedBlock(result? YES : NO, result, error); } } - (void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKReverseGeoCodeSearchResult *)result errorCode:(BMKSearchErrorCode)error { if (_reverseCompletedBlock) { _reverseCompletedBlock(result ? YES : NO, result, error); } } #pragma mark - BMKLocationManagerDelegate 定位代理 /** 用户拒绝开启定位服务等原因导致的定位失败会调用的方法 @brief 当定位发生错误时,会调用代理的此方法。 @param manager 定位 BMKLocationManager 类。 @param error 返回的错误,参考 CLError 。 */ - (void)BMKLocationManager:(BMKLocationManager *)manager didFailWithError:(NSError *)error { if (error) [self showErrorAlertWithError:error]; } /** 处理位置坐标更新 @brief 连续定位回调函数 @param manager 定位 BMKLocationManager 类。 @param location 定位结果,参考BMKLocation。 @param error 错误信息。 */ - (void)BMKLocationManager:(BMKLocationManager *)manager didUpdateLocation:(BMKLocation *)location orError:(NSError *)error { if (location) { self.userLocation.location = location.location; //实现该方法,否则定位图标不出现 [_mapView updateLocationData:self.userLocation]; //设置当前地图的中心点,改变该值时,地图的比例尺级别不会发生变化 _mapView.centerCoordinate = self.userLocation.location.coordinate; if (_locCompletedBlock) { _locCompletedBlock(location != nil , location.location); } [_locationManager stopUpdatingLocation]; //发起反向地理编码检索 // _searcher =[[BMKGeoCodeSearch alloc]init]; // _searcher.delegate = self; // BMKReverseGeoCodeSearchOption *reverseGeoCodeSearchOption = [[BMKReverseGeoCodeSearchOption alloc]init]; // reverseGeoCodeSearchOption.location = location.location.coordinate; // [_searcher reverseGeoCode:reverseGeoCodeSearchOption]; } } #pragma mark - Lazy loading - (BMKLocationManager *)locationManager { if (!_locationManager) { _locationManager = [[BMKLocationManager alloc] init]; _locationManager.delegate = self; _locationManager.coordinateType = BMKLocationCoordinateTypeBMK09LL; _locationManager.desiredAccuracy = kCLLocationAccuracyBest; _locationManager.activityType = CLActivityTypeAutomotiveNavigation; _locationManager.pausesLocationUpdatesAutomatically = NO; _locationManager.allowsBackgroundLocationUpdates = NO; _locationManager.locationTimeout = 10; } return _locationManager; } - (BMKUserLocation *)userLocation { if (!_userLocation) { _userLocation = [[BMKUserLocation alloc] init]; } return _userLocation; } - (BMKMapView *)mapView { if (!_mapView) { _mapView = [[BMKMapView alloc] initWithFrame:CGRectMake(0,0,_mapSize.width, _mapSize.height)]; //开启定位服务 [self beginLocation]; //设置mapView的代理 _mapView.delegate = self; //当前地图类型 _mapView.mapType = BMKMapTypeStandard; //设置地图比例尺级别 _mapView.zoomLevel = 14.7; //设置显示定位图层 _mapView.showsUserLocation = YES; //设置定位模式为普通模式 _mapView.userTrackingMode = BMKUserTrackingModeNone; //设定显式比例尺 _mapView.showMapScaleBar = YES; //配置定位图层个性化样式,初始化BMKLocationViewDisplayParam的实例 BMKLocationViewDisplayParam *param = [[BMKLocationViewDisplayParam alloc] init]; //设置定位图标(屏幕坐标)X轴偏移量为0 param.locationViewOffsetX = 0; //设置定位图标(屏幕坐标)Y轴偏移量为0 param.locationViewOffsetY = 0; //设置定位图层locationView在最上层(也可设置为在下层) param.locationViewHierarchy = LOCATION_VIEW_HIERARCHY_TOP; //设置显示精度圈(因“需求:可改变精度圈大小”,关闭默认精度圈) param.isAccuracyCircleShow = NO; //跟随态旋转角度是否生效 param.isRotateAngleValid = YES; //更新定位图层个性化样式 [_mapView updateLocationViewWithParam:param]; } return _mapView; } - (BMKGeoCodeSearch *)searcher { if (!_searcher) { _searcher =[[BMKGeoCodeSearch alloc]init]; _searcher.delegate = self; } return _searcher; } @end