欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-11-25 12:44:34
写在前面: 项目需求用到这个功能,主要目的是实现老师设置位置签到范围,学生在一定范围内进行签到的功能。 功能如下方截图: 屏幕快照 2019-01-28 上午...

写在前面:

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

功能如下方截图:

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

简要介绍:

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

功能实现

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

#import <baidumapapi_base/bmkbasecomponent.h>
#import <bmklocationkit/bmklocationcomponent.h>

加入功能代码:

#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中

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

遵循协议<bmkmapviewdelegate,bmklocationmanagerdelegate>

声明全局变量

@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文档中建议在以下代码中如此设置, 目的是控制内存

- (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;
 }
}

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

- (nsmutablearray *)annotationarr {
 
 if (!_annotationarr) {
  _annotationarr = [nsmutablearray array];
 }
 return _annotationarr;
}

- (nsmutablearray *)circlearr {
 if (!_circlearr) {
  _circlearr = [nsmutablearray array];
 }
 return _circlearr;
}

添加地图view

#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;
  
 }
}

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

#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];
}

请求定位,获取经纬度

#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);
 }];
}

地图长按选点功能实现:

//长按地图选点
- (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];
}

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

#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数组 */

#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;
}

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

总结

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