iOS实现百度地图定位签到功能

时间:2022-05-26 14:08:05

写在前面:

项目需求用到这个功能,主要目的是实现老师设置位置签到范围,学生在一定范围内进行签到的功能。

功能如下方截图:

iOS实现百度地图定位签到功能
屏幕快照 2019-01-28 上午10.29.26.png

简要介绍:

下面记录一下主要的实现流程,功能的实现主要是根据百度地图开发者官网提供的api文档,各项功能之间组合。百度地图的sdk现在分成了地图功能和定位功能两块不同的sdk,baidumapapi这个是基础的地图功能,bmklocationkit这个是定位功能。项目里实现定位签到功能用的的sdk包括上面说的这两个模块,所以在用cocopods引入framework的时候,需要引入: #百度地图 pod 'bmklocationkit' pod 'baidumapkit'

功能实现

一、在appdelegate.m文件中引入:

?
1
2
#import <baidumapapi_base/bmkbasecomponent.h>
#import <bmklocationkit/bmklocationcomponent.h>

加入功能代码:

?
1
2
3
4
5
6
7
8
9
10
11
#pragma mark 百度地图设置
- (void)configbaidumap {
 nsstring *ak = @"xxxx";
 bmkmapmanager *mapmanager = [[bmkmapmanager alloc] init];
 self.mapmanager = mapmanager;
 bool ret = [mapmanager start:ak generaldelegate:nil];
 [[bmklocationauth sharedinstance] checkpermisionwithkey:ak authdelegate:self];
 if (!ret) {
  nslog(@"manager start failed!");
 }
}

二、在用到地图定位功能的viewcontroller中

?
1
2
3
#import <bmklocationkit/bmklocationcomponent.h>
#import <baidumapapi_base/bmkbasecomponent.h>//引入base相关所有的头文件
#import <baidumapapi_map/bmkmapcomponent.h>//引入地图功能所有的头文件

遵循协议<bmkmapviewdelegate,bmklocationmanagerdelegate>

声明全局变量

?
1
2
3
4
5
6
@property (nonatomic, strong) bmkuserlocation *userlocation; //当前位置对象
@property (nonatomic, strong) bmklocationmanager *locationmanager;/** locationmanager*/
@property (nonatomic, strong) bmkmapview *mapview;/** 百度地图*/
//@property (nonatomic, strong) bmkpointannotation* annotation ;/** 标记*/
@property (nonatomic, strong) nsmutablearray *annotationarr;/** 标记数组*/
@property (nonatomic, strong) nsmutablearray *circlearr;/** 圆形数组*/

地图sdk文档中建议在以下代码中如此设置, 目的是控制内存

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)viewwillappear:(bool)animated {
 [super viewwillappear:animated];
 [_mapview viewwillappear];
 _mapview.delegate = self;
}
 
- (void)viewwilldisappear:(bool)animated {
 [super viewwilldisappear:animated];
 [_mapview viewwilldisappear];
 _mapview.delegate = nil;
}
 
- (void)dealloc {
 if (_mapview) {
  _mapview = nil;
 }
}

初始化数组,这两个数组在接下来会用到

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (nsmutablearray *)annotationarr {
 
 if (!_annotationarr) {
  _annotationarr = [nsmutablearray array];
 }
 return _annotationarr;
}
 
- (nsmutablearray *)circlearr {
 if (!_circlearr) {
  _circlearr = [nsmutablearray array];
 }
 return _circlearr;
}

添加地图view

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#pragma mark 添加地图
- (void)addsignmapbgview {
 if (!self.mapbgview) {
  uiview *mapbgview = [uiview new];
  self.mapbgview = mapbgview;
  mapbgview.backgroundcolor = [commutls colorwithhexstring:app_bgcolor];
  [self addsubview:mapbgview];
  [mapbgview makeconstraints:^(masconstraintmaker *make) {
   make.top.equalto(self.tipview.bottom);
   make.left.right.bottom.equalto(0);
  }];
  
  _mapview = [[bmkmapview alloc] initwithframe:cgrectzero];
//  _mapview.delegate = self;
  [_mapview setzoomlevel:21];//精确到5米
  _mapview.showsuserlocation = yes;//显示定位图层
  [mapbgview addsubview:_mapview];
  [_mapview makeconstraints:^(masconstraintmaker *make) {
   make.edges.equalto(0);
  }];
  _mapview.usertrackingmode = bmkusertrackingmodenone;
  
 }
}

初始化地图定位:这里我用的是一次定位而没有选择持续定位。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#pragma mark 初始化locationmanager
- (void)inituserlocationmanager {
 //因为mapview是在一个分离出来的view中创建的,所以在这里将signsettypeview中的mapview赋给当前viewcontroller的mapview;
 self.mapview = self.mainview.signsettypeview.mapview;
 self.mapview.delegate = self;
// self.annotation = [[bmkpointannotation alloc] init];
 
 // self.mapview是bmkmapview对象
 //精度圈设置
 bmklocationviewdisplayparam *param = [[bmklocationviewdisplayparam alloc] init];
 //设置显示精度圈,默认yes
 param.isaccuracycircleshow = yes;
 //精度圈 边框颜色
 param.accuracycirclestrokecolor = [uicolor colorwithred:242/255.0 green:129/255.0 blue:126/255.0 alpha:1];
 //精度圈 填充颜色
 param.accuracycirclefillcolor = [uicolor colorwithred:242/255.0 green:129/255.0 blue:126/255.0 alpha:0.3];
 [self.mapview updatelocationviewwithparam:param];
 
 self.userlocation = [[bmkuserlocation alloc] init];
 //初始化实例
 _locationmanager = [[bmklocationmanager alloc] init];
 //设置delegate
 _locationmanager.delegate = self;
 //设置返回位置的坐标系类型
 _locationmanager.coordinatetype = bmklocationcoordinatetypebmk09ll;
 //设置距离过滤参数
 _locationmanager.distancefilter = kcldistancefilternone;
 //设置预期精度参数
 _locationmanager.desiredaccuracy = kcllocationaccuracybest;
 //设置应用位置类型
 _locationmanager.activitytype = clactivitytypeautomotivenavigation;
 //设置是否自动停止位置更新
 _locationmanager.pauseslocationupdatesautomatically = no;
 //设置是否允许后台定位
 //_locationmanager.allowsbackgroundlocationupdates = yes;
 //设置位置获取超时时间
 _locationmanager.locationtimeout = 15;
 //设置获取地址信息超时时间
 _locationmanager.regeocodetimeout = 15;
 //请求一次定位
 [self requestlocation];
}

请求定位,获取经纬度

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#pragma mark 请求定位
- (void)requestlocation {
 
 [_locationmanager requestlocationwithregeocode:yes withnetworkstate:yes completionblock:^(bmklocation * _nullable location, bmklocationnetworkstate state, nserror * _nullable error) {
  if (error)
  {
   nslog(@"locerror:{%ld - %@};", (long)error.code, error.localizeddescription);
  }
  if (location) {//得到定位信息,添加annotation
   
   if (location.location) {
    nslog(@"loc = %@",location.location);
   }
   if (location.rgcdata) {
    nslog(@"rgc = %@",[location.rgcdata description]);
   }
   
   if (!location) {
    return;
   }
   if (!self.userlocation) {
    self.userlocation = [[bmkuserlocation alloc] init];
   }
   self.userlocation.location = location.location;
   [self.mapview updatelocationdata:self.userlocation];
   cllocationcoordinate2d mycoordinate = location.location.coordinate;
   self.mapview.centercoordinate = mycoordinate;
   
   //赋予初始值
   self.viewmodel.lat = [nsstring stringwithformat:@"%f", location.location.coordinate.latitude];
   self.viewmodel.lng = [nsstring stringwithformat:@"%f",location.location.coordinate.longitude];
   self.viewmodel.radius = @"50";
   
   //打印经纬度
   nslog(@"didupdateuserlocation lat %f,long %f",location.location.coordinate.latitude,location.location.coordinate.longitude);
  }
  nslog(@"netstate = %d",state);
 }];
}

地图长按选点功能实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//长按地图选点
- (void)mapview:(bmkmapview *)mapview onlongclick:(cllocationcoordinate2d)coordinate {
 
 if (self.annotationarr.count > 0) {
  [mapview removeannotations:self.annotationarr];
  [self.annotationarr removeallobjects];
  
  bmkpointannotation *annotation = [[bmkpointannotation alloc]init];
  annotation.coordinate = coordinate;
  [self.annotationarr addobject:annotation];
  [mapview addannotations:self.annotationarr];
 } else {
  bmkpointannotation *annotation = [[bmkpointannotation alloc]init];
  annotation.coordinate = coordinate;
  [self.annotationarr addobject:annotation];
  [mapview addannotations:self.annotationarr];
 }
 //弹出半径选择框
 [self showlocationselectradiusviewwithcoordinate:coordinate];
}

选点后弹出选择定位范围弹框

?
1
2
3
4
5
6
7
8
9
10
11
12
#pragma mark 弹出位置弹框
- (void)showlocationselectradiusviewwithcoordinate:(cllocationcoordinate2d)coordinate {
 extraactlocationsignpopview *popview = [extraactlocationsignpopview new];
 [popview show];
 @weakify(self);
 [popview.locatioonsuresignal subscribenext:^(nsstring *x) {
  @strongify(self);
  self.viewmodel.radius = x;
  cgfloat radius = [x floatvalue];
  [self circlewithcenterwithcoordinate2d:coordinate radius:radius];
 }];
}

设置好定位点以及半径范围后绘制范围圈,开始的时候声明的circlearr在这里用来盛放添加的区域圆形,在添加新的圆圈的时候,将之前旧的移除,保证每次绘制的范围都是最新的,同理annotationarr也是这个功能,因为api有提供的- (void)addoverlays:(nsarray *)overlays;这个方法:/** *向地图窗口添加一组overlay,需要实现bmkmapviewdelegate的-mapview:viewforoverlay:函数来生成标注对应的view overlays 要添加的overlay数组 */

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#pragma mark 添加区域圆形覆盖
- (void)circlewithcenterwithcoordinate2d:(cllocationcoordinate2d )coor radius:(cgfloat)radius {
 
 nslog(@"coordinate lat %f,long %f",coor.latitude,coor.longitude);
 //赋予点击选点值
 self.viewmodel.lat = [nsstring stringwithformat:@"%f", coor.latitude];
 self.viewmodel.lng = [nsstring stringwithformat:@"%f",coor.longitude];
 
 if (self.circlearr.count > 0) {
  [_mapview removeoverlays:self.circlearr];
  [self.circlearr removeallobjects];
  
  bmkcircle *circle = [bmkcircle circlewithcentercoordinate:coor radius:radius];
  [self.circlearr addobject:circle];
  [_mapview addoverlays:self.circlearr];
 } else {
  bmkcircle *circle = [bmkcircle circlewithcentercoordinate:coor radius:radius];
  [self.circlearr addobject:circle];
  [_mapview addoverlays:self.circlearr];
 }
}
 
#pragma mark 重绘overlay
- (bmkoverlayview *)mapview:(bmkmapview *)mapview viewforoverlay:(id <bmkoverlay>)overlay{
 if ([overlay iskindofclass:[bmkcircle class]]){
  bmkcircleview* circleview = [[bmkcircleview alloc] initwithoverlay:overlay];
  circleview.fillcolor = [uicolor colorwithred:33/255.0 green:196/255.0 blue:206/255.0 alpha:0.3];
  circleview.strokecolor = [uicolor colorwithred:33/255.0 green:196/255.0 blue:206/255.0 alpha:1];
  circleview.linewidth = 1.0;
  return circleview;
 }
 return nil;
}

至此,在地图上选点进行签到功能基本实现,另外,关于 自定义的范围圆圈的颜色,边框大小都是可以自定义的,选点的标记也是可以自定义的,官方文档有说明

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:https://www.jianshu.com/p/e948a3bfe600