MapManager.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. //
  2. // MapManager.m
  3. // jiaPei
  4. //
  5. // Created by 张嵘 on 2018/9/20.
  6. // Copyright © 2018年 JCZ. All rights reserved.
  7. //
  8. #import "MapManager.h"
  9. static MapManager *manger = nil;
  10. static dispatch_once_t onceToken;
  11. //复用annotationView的指定唯一标识
  12. static NSString *annotationViewIdentifier = @"com.Baidu.BMKPointAnnotation";
  13. @interface MapManager () <BMKLocationAuthDelegate, BMKLocationManagerDelegate, BMKMapViewDelegate, BMKGeneralDelegate, BMKGeoCodeSearchDelegate>
  14. @property (nonatomic, strong) BMKMapManager *mapManager; //主引擎类
  15. @property (nonatomic, strong) BMKLocationManager *locationManager; //定位对象
  16. @property (nonatomic, strong) BMKUserLocation *userLocation;//当前位置对象
  17. @property (nonatomic, assign) BOOL locationLock;//单次定位锁
  18. @property (nonatomic, strong) LocCompletedBlock locCompletedBlock;//定位回调
  19. @property (nonatomic, strong) BMKMapView *mapView;//地图View类
  20. @property (nonatomic, assign) CGSize mapSize;//地图大小
  21. @property (nonatomic, strong) BMKGeoCodeSearch *searcher;//搜索对象
  22. @property (nonatomic, strong) SearchCompletedBlock searchCompletedBlock;//搜索回调
  23. @property (nonatomic, strong) ReverseCompletedBlock reverseCompletedBlock;//反地理编码回调
  24. @end
  25. @implementation MapManager
  26. + (MapManager *)sharedManager {
  27. dispatch_once(&onceToken, ^{
  28. manger = [[self alloc] init];
  29. });
  30. return manger;
  31. }
  32. + (float)radians:(float)degrees{
  33. return (degrees*3.14159265)/180.0;
  34. }
  35. + (float)getDistance:(float)lat1 lng1:(float)lng1 lat2:(float)lat2 lng2:(float)lng2{
  36. //地球半径
  37. int R = 6378137;
  38. //将角度转为弧度
  39. float radLat1 = [self radians:lat1];
  40. float radLat2 = [self radians:lat2];
  41. float radLng1 = [self radians:lng1];
  42. float radLng2 = [self radians:lng2];
  43. //结果
  44. float s = acos(cos(radLat1)*cos(radLat2)*cos(radLng1-radLng2)+sin(radLat1)*sin(radLat2))*R;
  45. //精度
  46. s = round(s* 10000)/10000;
  47. return round(s);
  48. }
  49. - (instancetype)init {
  50. self = [super init];
  51. if (self) {
  52. // 初始化定位SDK
  53. [[BMKLocationAuth sharedInstance] checkPermisionWithKey:BaiDuMapAK authDelegate:self];
  54. //要使用百度地图,请先启动BMKMapManager
  55. [BMKMapManager setAgreePrivacy:YES];
  56. _mapManager = [[BMKMapManager alloc] init];
  57. // ‼️重要:设置用户是否同意SDK隐私协议,请务必在BMKLocationManager和BMKGeoFenceManager实例化之前调用,否则实例化失败
  58. [[BMKLocationAuth sharedInstance] setAgreePrivacy:YES];
  59. /**
  60. 百度地图SDK所有API均支持百度坐标(BD09)和国测局坐标(GCJ02),用此方法设置您使用的坐标类型.
  61. 默认是BD09(BMK_COORDTYPE_BD09LL)坐标.
  62. 如果需要使用GCJ02坐标,需要设置CoordinateType为:BMK_COORDTYPE_COMMON.
  63. */
  64. if ([BMKMapManager setCoordinateTypeUsedInBaiduMapSDK:BMK_COORDTYPE_BD09LL]) {
  65. NSLog(@"经纬度类型设置成功");
  66. } else {
  67. NSLog(@"经纬度类型设置失败");
  68. }
  69. //启动引擎并设置AK并设置delegate
  70. BOOL result = [_mapManager start:BaiDuMapAK generalDelegate:self];
  71. if (!result) {
  72. NSLog(@"启动引擎失败");
  73. }
  74. }
  75. return self;
  76. }
  77. - (void)dealloc {
  78. _mapView.delegate = nil;
  79. }
  80. #pragma mark - Custom Way
  81. /**
  82. 根据大小创建地图
  83. @param size 大小
  84. @return 返回地图
  85. */
  86. - (BMKMapView *)getMapViewWithSize:(CGSize)size {
  87. _mapSize = size;
  88. return self.mapView;
  89. }
  90. /**
  91. 单次定位
  92. @param completeBlock 定位回调
  93. */
  94. - (void)updateLocationWithCompleteBlock:(LocCompletedBlock)completeBlock {
  95. @weakify(self)
  96. self.locationLock = YES;
  97. self.locationManager.distanceFilter = kCLDistanceFilterNone;
  98. [self.locationManager requestLocationWithReGeocode:YES withNetworkState:YES completionBlock:^(BMKLocation * _Nullable location, BMKLocationNetworkState state, NSError * _Nullable error) {
  99. @strongify(self)
  100. if (location != nil) {
  101. self.locationLock = NO;
  102. if (completeBlock) {
  103. completeBlock(location != nil , location.location, location);
  104. }
  105. }else{
  106. if (completeBlock) {
  107. completeBlock(NO , location.location, location);
  108. }
  109. }
  110. if (error) [self showErrorAlertWithError:error];
  111. }];
  112. }
  113. /**
  114. 连续定位
  115. @param distanceFilter 设定定位的最小更新距离。默认为 kCLDistanceFilterNone
  116. @param completeBlock 定位回调
  117. */
  118. - (void)updateLocationWithDistanceFilter:(NSInteger)distanceFilter CompleteBlock:(LocCompletedBlock)completeBlock {
  119. [self.locationManager startUpdatingLocation];
  120. self.locationManager.distanceFilter = distanceFilter? distanceFilter : kCLDistanceFilterNone;
  121. _locCompletedBlock = completeBlock;
  122. }
  123. /**
  124. 返回地址信息搜索结果
  125. @param address 地址(必填)
  126. @param city 城市(选填)
  127. @param completeBlock 搜索回调
  128. */
  129. - (void)onGetGeoCodeWithAddress:(NSString *)address City:(NSString *)city completeBlock:(SearchCompletedBlock)completeBlock {
  130. BMKGeoCodeSearchOption *geoCodeSearchOption = [[BMKGeoCodeSearchOption alloc]init];
  131. geoCodeSearchOption.city= city;
  132. geoCodeSearchOption.address = address;
  133. [self.searcher geoCode:geoCodeSearchOption];
  134. _searchCompletedBlock = completeBlock;
  135. }
  136. /**
  137. 返回反地理编码搜索结果
  138. @param location 定位
  139. @param completeBlock 搜索回调
  140. */
  141. - (void)onGetReverseGeoCodeWithLocation:(CLLocation *)location completeBlock:(ReverseCompletedBlock)completeBlock {
  142. BMKReverseGeoCodeSearchOption *reverseGeoCodeSearchOption = [[BMKReverseGeoCodeSearchOption alloc]init];
  143. reverseGeoCodeSearchOption.location = location.coordinate;
  144. [self.searcher reverseGeoCode:reverseGeoCodeSearchOption];
  145. _reverseCompletedBlock = completeBlock;
  146. }
  147. /**
  148. 错误弹窗
  149. */
  150. - (void)showErrorAlertWithError:(NSError *)error {
  151. switch (error.code) {
  152. case BMKLocationErrorDenied: {
  153. if (!RQ_AD_MANAGER.isFirstAppLoad) {
  154. ShowMsg(@"请在iPhone的“设置”-“隐私”-“定位服务”功能中,找到“极速驾培”打开位置访问权限");
  155. // [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"请在iPhone的“设置”-“隐私”-“定位服务”功能中,找到“极速驾培”打开位置访问权限" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:nil];
  156. }
  157. }
  158. break;
  159. default:
  160. break;
  161. }
  162. [_locationManager stopUpdatingLocation];
  163. }
  164. /**
  165. 开始定位
  166. */
  167. - (void)beginLocation{
  168. [self.locationManager startUpdatingLocation];
  169. [self.locationManager startUpdatingHeading];
  170. }
  171. #pragma mark - BMKLocationAuthDelegate 定位鉴权代理
  172. /**
  173. * @brief 返回授权验证错误
  174. * @param iError 错误号 : 为0时验证通过,具体参加BMKLocationAuthErrorCode
  175. */
  176. - (void)onCheckPermissionState:(BMKLocationAuthErrorCode)iError {
  177. switch (iError) {
  178. case BMKLocationAuthErrorUnknown:
  179. NSLog(@"未知错误");
  180. break;
  181. case BMKLocationAuthErrorSuccess:
  182. NSLog(@"鉴权成功");
  183. break;
  184. case BMKLocationAuthErrorNetworkFailed:
  185. NSLog(@"因网络鉴权失败");
  186. break;
  187. case BMKLocationAuthErrorFailed:
  188. NSLog(@"KEY非法鉴权失败");
  189. break;
  190. default:
  191. break;
  192. }
  193. }
  194. /**
  195. 联网结果回调
  196. @param iError 联网结果错误码信息,0代表联网成功
  197. */
  198. - (void)onGetNetworkState:(int)iError {
  199. if (0 == iError) {
  200. NSLog(@"联网成功");
  201. } else {
  202. NSLog(@"联网失败:%d", iError);
  203. }
  204. }
  205. #pragma mark - BMKMapViewDelegate 地图代理
  206. #pragma mark - BMKGeoCodeSearchDelegate 搜索代理
  207. - (void)onGetGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKGeoCodeSearchResult *)result errorCode:(BMKSearchErrorCode)error {
  208. if (_searchCompletedBlock) {
  209. _searchCompletedBlock(result? YES : NO, result, error);
  210. }
  211. }
  212. - (void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKReverseGeoCodeSearchResult *)result errorCode:(BMKSearchErrorCode)error {
  213. if (_reverseCompletedBlock) {
  214. _reverseCompletedBlock(result ? YES : NO, result, error);
  215. }
  216. }
  217. #pragma mark - BMKLocationManagerDelegate 定位代理
  218. /**
  219. 用户拒绝开启定位服务等原因导致的定位失败会调用的方法
  220. @brief 当定位发生错误时,会调用代理的此方法。
  221. @param manager 定位 BMKLocationManager 类。
  222. @param error 返回的错误,参考 CLError 。
  223. */
  224. - (void)BMKLocationManager:(BMKLocationManager *)manager didFailWithError:(NSError *)error {
  225. if (error) [self showErrorAlertWithError:error];
  226. }
  227. /**
  228. 处理位置坐标更新
  229. @brief 连续定位回调函数
  230. @param manager 定位 BMKLocationManager 类。
  231. @param location 定位结果,参考BMKLocation。
  232. @param error 错误信息。
  233. */
  234. - (void)BMKLocationManager:(BMKLocationManager *)manager didUpdateLocation:(BMKLocation *)location orError:(NSError *)error {
  235. if (location) {
  236. self.userLocation.location = location.location;
  237. //实现该方法,否则定位图标不出现
  238. [_mapView updateLocationData:self.userLocation];
  239. //设置当前地图的中心点,改变该值时,地图的比例尺级别不会发生变化
  240. _mapView.centerCoordinate = self.userLocation.location.coordinate;
  241. if (_locCompletedBlock) {
  242. _locCompletedBlock(location != nil , location.location, location);
  243. }
  244. [_locationManager stopUpdatingLocation];
  245. //发起反向地理编码检索
  246. // _searcher =[[BMKGeoCodeSearch alloc]init];
  247. // _searcher.delegate = self;
  248. // BMKReverseGeoCodeSearchOption *reverseGeoCodeSearchOption = [[BMKReverseGeoCodeSearchOption alloc]init];
  249. // reverseGeoCodeSearchOption.location = location.location.coordinate;
  250. // [_searcher reverseGeoCode:reverseGeoCodeSearchOption];
  251. }
  252. }
  253. #pragma mark - Lazy loading
  254. - (BMKLocationManager *)locationManager {
  255. if (!_locationManager) {
  256. _locationManager = [[BMKLocationManager alloc] init];
  257. _locationManager.delegate = self;
  258. _locationManager.coordinateType = BMKLocationCoordinateTypeBMK09LL;
  259. _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
  260. _locationManager.activityType = CLActivityTypeAutomotiveNavigation;
  261. _locationManager.pausesLocationUpdatesAutomatically = NO;
  262. _locationManager.allowsBackgroundLocationUpdates = NO;
  263. _locationManager.locationTimeout = 10;
  264. }
  265. return _locationManager;
  266. }
  267. - (BMKUserLocation *)userLocation {
  268. if (!_userLocation) {
  269. _userLocation = [[BMKUserLocation alloc] init];
  270. }
  271. return _userLocation;
  272. }
  273. - (BMKMapView *)mapView {
  274. if (!_mapView) {
  275. _mapView = [[BMKMapView alloc] initWithFrame:CGRectMake(0,0,_mapSize.width, _mapSize.height)];
  276. //开启定位服务
  277. [self beginLocation];
  278. //设置mapView的代理
  279. _mapView.delegate = self;
  280. //当前地图类型
  281. _mapView.mapType = BMKMapTypeStandard;
  282. //设置地图比例尺级别
  283. _mapView.zoomLevel = 14.7;
  284. //设置显示定位图层
  285. _mapView.showsUserLocation = YES;
  286. //设置定位模式为普通模式
  287. _mapView.userTrackingMode = BMKUserTrackingModeNone;
  288. //设定显式比例尺
  289. _mapView.showMapScaleBar = YES;
  290. //配置定位图层个性化样式,初始化BMKLocationViewDisplayParam的实例
  291. BMKLocationViewDisplayParam *param = [[BMKLocationViewDisplayParam alloc] init];
  292. //设置定位图标(屏幕坐标)X轴偏移量为0
  293. param.locationViewOffsetX = 0;
  294. //设置定位图标(屏幕坐标)Y轴偏移量为0
  295. param.locationViewOffsetY = 0;
  296. //设置定位图层locationView在最上层(也可设置为在下层)
  297. param.locationViewHierarchy = LOCATION_VIEW_HIERARCHY_TOP;
  298. //设置显示精度圈(因“需求:可改变精度圈大小”,关闭默认精度圈)
  299. param.isAccuracyCircleShow = NO;
  300. //跟随态旋转角度是否生效
  301. param.isRotateAngleValid = YES;
  302. //更新定位图层个性化样式
  303. [_mapView updateLocationViewWithParam:param];
  304. }
  305. return _mapView;
  306. }
  307. - (BMKGeoCodeSearch *)searcher {
  308. if (!_searcher) {
  309. _searcher =[[BMKGeoCodeSearch alloc]init];
  310. _searcher.delegate = self;
  311. }
  312. return _searcher;
  313. }
  314. @end