iOS原生地图热点搜索和基本使用汇总
程序员文章站
2023-04-08 12:14:01
1. 创建之前的准备工作
1.1 在info.plist文件中添加下面两句话
nslocationalwaysusagedescription —> 确定定位吗?亲
//请求的授权...
1. 创建之前的准备工作
1.1 在info.plist文件中添加下面两句话
nslocationalwaysusagedescription —> 确定定位吗?亲
//请求的授权,除了可以在app打开时允许定位服务,也可以在app进入后台仍然可以使用定位服务(永久) --> 与上边一个可以二选一
[_locationmanager requestalwaysauthorization];
nslocationwheninuseusagedescripyion —>需要定位吗?
//此方法请求的授权,仅限于用户在打开使用app时允许使用的定位服务(在应用使用期间)
[_locationmanager requestwheninuseauthorization];
1.2 导入库文件 mapkit.framework 和 corelocation.framework
2. 工程创建说明 ---> 使用系统自带的mkpointannotation、mkpinannotationview及自定义 mkpointannotation、mkpinannotationview
以下是viewcontroller.m 文件
2.1viewdidload 中的加载
1 #import "viewcontroller.h" 2 #import "mapkit/mapkit.h" 3 #import "mypointannotation.h" 4 #import "myannotationview.h" 5 6 @interface viewcontroller () { 7 8 mkmapview *_mapview; //地图对象 9 uilabel *_userlocationlable; //查看用户坐标 10 } 11 12 @end 13 14 @implementation viewcontroller 15 16 - (void)viewdidload { 17 [super viewdidload]; 18 19 //调用创建地图视图的方法 20 [self createmapview]; 21 //调用创建大头针的方法 22 [self createannotations]; 23 //调用这个方法调用所有的覆盖层的方法 24 [self overlay]; 25 //调用创建ui的方法 26 [self createui]; 27 } 28 29 @end
2.2创建地图视图的方法
1 //创建地图视图的方法 2 - (void)createmapview { 3 //创建地图对象 4 _mapview = [[mkmapview alloc] initwithframe:self.view.bounds]; 5 //设置map的类型 或地图模式 6 _mapview.maptype = mkmaptypestandard; 7 /* 8 mkmaptypestandard = 0, 纸张地图 标准地图 9 mkmaptypesatellite, 纯卫星地图 10 mkmaptypehybrid, 混合式地图 描述的卫星图 11 */ 12 //设置map的初始位置 13 //创建地理坐标2d 需要经度和纬度 如:经度:120.366486 纬度:36.083743 14 cllocationcoordinate2d location = cllocationcoordinate2dmake(36.083743, 120.366486); 15 //起始时 锁定一个矩形为1000 x 1000米的方位 ,坐标点location 16 _mapview.region = mkcoordinateregionmakewithdistance(location, 1000, 1000); 17 //设置地图能否放大缩小 18 _mapview.zoomenabled = yes; 19 //设置地图能否滚动 20 _mapview.scrollenabled = yes; 21 //设置显示用户的位置 先判断是否开始了定位服务 22 if ([cllocationmanager locationservicesenabled] == yes) { 23 //显示用户的位置 24 _mapview.showsuserlocation = yes; 25 //设置用户的基本跟踪状态 26 [_mapview setusertrackingmode:mkusertrackingmodefollowwithheading animated:yes]; 27 28 /* 29 mkusertrackingmodenone = 0, 不尾随 一般不设 30 mkusertrackingmodefollow, 尾随用户位置,地图保存正向(北方向) 31 mkusertrackingmodefollowwithheading 随着地图旋转而尾随(地图方向和设备方向同步) 32 */ 33 } 34 //设置代理 需遵守mkmapviewdelegate代理协议 35 _mapview.delegate = self; 36 //将地图加入到self.view上 37 [self.view addsubview:_mapview]; 38 } 39 40 #pragma mark - 地图协议中的方法 - 41 - (mkannotationview *)mapview:(mkmapview *)mapview viewforannotation:(id)annotation { 42 43 //这里判断必须要加,这个方法在刷新时会将用户的位置也会传到这个方法里,所以需要判断,如果不是大头针就是用户坐标点(蓝点),如果是蓝点(用户坐标点) 直接返回nil 44 if ([annotation iskindofclass:[mkpointannotation class]] == no) { 45 return nil; 46 } 47 48 //调用系统的方法 49 // mkpinannotationview *annotationview = [self systemmethodwithmapview:mapview andannotation:annotation]; 50 51 //调用自定义的方法 52 mkpinannotationview *annotationview = [self custommethodwithmapview:mapview andannotation:annotation]; 53 54 return annotationview; 55 } 56 57 //自定义的方法 58 - (mkpinannotationview *)custommethodwithmapview:(mkmapview *)mapview andannotation:(mkpointannotation *)annotation { 59 myannotationview *annotationview = (myannotationview *)[mapview dequeuereusableannotationviewwithidentifier:@"customannotationview"]; 60 61 if (annotationview == nil) { 62 63 64 annotationview = [[myannotationview alloc] initwithannotation:annotation reuseidentifier:@"customannotationview"]; 65 66 }else { 67 68 annotationview.annotation = annotation; 69 } 70 71 72 73 return annotationview; 74 } 75 76 77 //系统方法 78 - (mkpinannotationview *)systemmethodwithmapview:(mkmapview *)mapview andannotation:(mkpointannotation *)annotation { 79 80 // 类似于tableview的复用机制那个方法 81 mkpinannotationview *annotationview = (mkpinannotationview *)[mapview dequeuereusableannotationviewwithidentifier:@"annotationview"]; 82 if (annotationview == nil) { 83 //如果从队列取 没有的话,需要创建新的大头针视图 84 annotationview = [[mkpinannotationview alloc] initwithannotation:annotation reuseidentifier:@"annotationview"]; 85 //设置大头针的色彩,默认是红色,还有绿色和紫色(了解) 86 annotationview.pincolor = mkpinannotationcolorpurple; 87 //设置允许显示气泡(重要) 88 annotationview.canshowcallout = yes; 89 //设置下坠动画 (从上往下掉下来) 默认为no 90 annotationview.animatesdrop = yes; 91 //设置是佛可以拖拽 92 annotationview.draggable = yes; 93 94 }else { 95 96 //如果有空闲,拿队列里空闲的view 然后显示大头针 97 annotationview.annotation = annotation; 98 99 } 100 return annotationview; 101 }
2.3 创建大头针的方法
1 //创建大头针的方法 2 - (void)createannotations { 3 //创建大头针1 4 mkpointannotation *annotation1 = [[mkpointannotation alloc] init]; 5 //设置title 6 annotation1.title = @"不知道是哪"; 7 //设置子title 8 annotation1.subtitle = @"真不知道是哪儿"; 9 //设置大头针的经纬度坐标 10 annotation1.coordinate = cllocationcoordinate2dmake(-39.89, -79.88); 11 //把大头针1加入到地图上 12 [_mapview addannotation:annotation1]; 13 //创建大头针2 14 mkpointannotation *annotation2 = [[mkpointannotation alloc] init]; 15 annotation2.title = @"南半球"; 16 annotation2.subtitle = @"真是南半球"; 17 annotation2.coordinate = cllocationcoordinate2dmake(-80.89, 156.456); 18 [_mapview addannotation:annotation2]; 19 //自定义方式创建大头针3 20 mypointannotation *annotation3 = [[mypointannotation alloc] initwithcoordinate:cllocationcoordinate2dmake(40.5, -88.7) title:@"第一个位置" subtitle:@"这里风景优美" information:@"这里是*旅游景点"]; 21 //自定义方式创建大头针4 22 mypointannotation *annotation4 = [[mypointannotation alloc] initwithcoordinate:cllocationcoordinate2dmake(37.68, -96.54) title:@"第二个位置" subtitle:@"这里有点冷" information:@"世界冰展所在地"]; 23 //将大头针3和4一块加入到地图上 用addannotations 24 [_mapview addannotations:@[annotation3,annotation4]]; 25 26 //将地图滚动到大头针3的位置 27 _mapview.centercoordinate = annotation1.coordinate; 28 29 }
2.4这个方法调用所有的覆盖层的方法
1 //这个方法调用所有的覆盖层的方法 2 - (void)overlay { 3 4 //调用绘制线的方法 5 [self pathoverlay]; 6 7 //调用多边形图层的方法 8 [self polyoverlay]; 9 10 //调用绘制圆的图层的方法 11 [self circleoverlay]; 12 13 } 14 15 //绘制圆的图层的方法 16 - (void)circleoverlay { 17 //圆图层和annotation一样需要添加到地图上,每个图层绘制都需要实现管理图层方法 18 cllocationcoordinate2d centerlocation = cllocationcoordinate2dmake(37.68, -96.54); 19 //绘制圆 20 mkcircle *circleoverlay = [mkcircle circlewithcentercoordinate:centerlocation radius:100000]; 21 //添加到地图上 22 [_mapview addoverlay:circleoverlay]; 23 24 } 25 26 //多边形图层的方法 27 - (void)polyoverlay { 28 //设置多边形的角的坐标,记住一定要首尾相连 29 30 cllocationcoordinate2d ploycoords[5] = { 31 cllocationcoordinate2dmake(35.443, -77.876), 32 cllocationcoordinate2dmake(36.553, -77.976), 33 cllocationcoordinate2dmake(35.553, -79.567), 34 cllocationcoordinate2dmake(34.443, -79.567), 35 cllocationcoordinate2dmake(35.443, -77.876) 36 37 38 }; 39 40 mkpolygon *polygonoverlay = [mkpolygon polygonwithcoordinates:ploycoords count:5]; 41 //添加到地图上 42 [_mapview addoverlay:polygonoverlay]; 43 } 44 45 //绘制线的方法 46 - (void)pathoverlay { 47 cllocationcoordinate2d pathcoords[6] = { 48 49 cllocationcoordinate2dmake(33.123, -77.456), 50 cllocationcoordinate2dmake(34.123, -78.456), 51 cllocationcoordinate2dmake(32.123, -79.456), 52 cllocationcoordinate2dmake(36.123, -71.456), 53 cllocationcoordinate2dmake(35.123, -70.456), 54 cllocationcoordinate2dmake(36.123, 73.456) 55 56 }; 57 58 //创建图层 59 mkpolyline *pathoverlay = [mkpolyline polylinewithcoordinates:pathcoords count:6]; 60 //添加到地图上 61 [_mapview addoverlay:pathoverlay]; 62 63 64 } 65 66 //管理图层视图 67 - (mkoverlayrenderer *)mapview:(mkmapview *)mapview rendererforoverlay:(id)overlay { 68 69 if ([overlay iskindofclass:[mkpolyline class]] == yes) { 70 mkpolylinerenderer *line = [[mkpolylinerenderer alloc] initwithoverlay:overlay]; 71 //线的宽度 72 line.linewidth = 2; 73 //设置线的颜色 74 line.strokecolor = [uicolor bluecolor]; 75 76 return line; 77 78 }else if ([overlay iskindofclass:[mkpolygon class]] == yes) { 79 80 mkpolygonrenderer *poly = [[mkpolygonrenderer alloc] initwithoverlay:overlay]; 81 //设置线宽 82 poly.linewidth = 1; 83 //设置边缘颜色 84 poly.strokecolor = [uicolor greencolor]; 85 //设置填充颜色 86 poly.fillcolor = [[uicolor redcolor] colorwithalphacomponent:0.5]; 87 88 return poly; 89 90 }else if ([overlay iskindofclass:[mkcircle class]] == yes) { 91 92 //创建圆视图 所有的视图都是overlay添加到构造方法参数 93 mkcirclerenderer *circle = [[mkcirclerenderer alloc] initwithoverlay:overlay]; 94 //设置边缘宽度 95 circle.linewidth = 1; 96 //设置边缘颜色 97 circle.strokecolor = [uicolor redcolor]; 98 //设置填充颜色 透明度0.4 99 circle.fillcolor = [[uicolor greencolor] colorwithalphacomponent:0.4]; 100 101 return circle; 102 } 103 104 return nil; 105 }
2.5 创建ui的方法 在创建该方法之前需要在appdelegate.m 文件中将viewcontroller包装成导航控制器
1 //创建ui的方法 2 - (void)createui { 3 4 _userlocationlable = [[uilabel alloc] initwithframe:cgrectmake(0, 64, 320, 80)]; 5 [self.view addsubview:_userlocationlable]; 6 //创建barbuttonitem 这个是用户定位(跟随),参数放入一个mapview类型的地图对象 7 mkusertrackingbarbuttonitem *item = [[mkusertrackingbarbuttonitem alloc] initwithmapview:_mapview]; 8 //设置导航左边的barbuttonitem 9 self.navigationitem.leftbarbuttonitem = item; 10 11 uibutton *hotsearchbutton = [uibutton buttonwithtype:uibuttontypecustom]; 12 hotsearchbutton.frame = cgrectmake(0, 64, 100, 40); 13 [hotsearchbutton settitle:@"热点搜索" forstate:uicontrolstatenormal]; 14 15 [hotsearchbutton addtarget:self action:@selector(hotseatch) forcontrolevents:uicontroleventtouchupinside]; 16 17 18 [hotsearchbutton settitlecolor:[uicolor bluecolor] forstate:uicontrolstatenormal]; 19 20 [self.view addsubview:hotsearchbutton]; 21 22 23 uibutton *keywordsearchbutton = [uibutton buttonwithtype:uibuttontypecustom]; 24 25 keywordsearchbutton.frame = cgrectmake(100, 64, 100, 40); 26 27 [keywordsearchbutton settitle:@"关键字搜索" forstate:uicontrolstatenormal]; 28 29 [keywordsearchbutton addtarget:self action:@selector(keywordsearch) forcontrolevents:uicontroleventtouchupinside]; 30 [keywordsearchbutton settitlecolor:[uicolor bluecolor] forstate:uicontrolstatenormal]; 31 32 [self.view addsubview:keywordsearchbutton]; 33 34 //添加一个长按的手势 用长按的手势添加大头针 35 uilongpressgesturerecognizer *longpress = [[uilongpressgesturerecognizer alloc] initwithtarget:self action:@selector(longpress:)]; 36 longpress.minimumpressduration = 1; 37 //长按手势加入到地图 38 [_mapview addgesturerecognizer:longpress]; 39 } 40 41 //长按手势执行的方法 42 - (void)longpress:(uilongpressgesturerecognizer *)longpress { 43 //注:一定别忘了判断 44 //判断长按手势状态 如果是开始的状态,就执行判断题 45 if (longpress.state == uigesturerecognizerstatebegan) { 46 //在地图上找到cgpoint坐标(屏幕坐标) 47 cgpoint point = [longpress locationinview:_mapview]; 48 //屏幕坐标转成经纬度坐标 49 cllocationcoordinate2d coordinate = [_mapview convertpoint:point tocoordinatefromview:_mapview]; 50 //创建大头针 51 52 mypointannotation *annotation = [[mypointannotation alloc] initwithcoordinate:coordinate title:@"手势加入" subtitle:@"长按手势" information:@"长按手势信息"]; 53 54 55 //加入到地图上 56 [_mapview addannotation:annotation]; 57 58 } 59 60 61 } 62 63 64 - (void)hotseatch { 65 //创建本地搜索请求 66 mklocalsearchrequest *request = [[mklocalsearchrequest alloc] init]; 67 //设置搜索热点词(自然语言) 68 request.naturallanguagequery = @"学校"; 69 //设置搜索范围,以某个原点为中心,向外扩展一段经纬度距离范围 70 cllocationcoordinate2d origionpoint = cllocationcoordinate2dmake(36.08397, 120.37126); 71 //设置经纬度跨越范围 72 mkcoordinatespan span = mkcoordinatespanmake(0.3, 0.3); 73 //设置经纬度搜索区域 74 mkcoordinateregion region = mkcoordinateregionmake(origionpoint, span); 75 //将区域赋值给搜索请求对象中的region属性中 76 request.region = region; 77 //将地图移动到该区域 78 [_mapview setregion:region]; 79 80 //创建本地搜索对象 81 mklocalsearch *search = [[mklocalsearch alloc] initwithrequest:request]; 82 //开启搜索 83 [search startwithcompletionhandler:^(mklocalsearchresponse * _nullable response, nserror * _nullable error) { 84 85 if (error == nil) { 86 87 //搜索成功 88 //获取搜索结果 89 nsarray *arrresult = response.mapitems; 90 91 for (mkmapitem *item in arrresult) { 92 93 //先取出地图目的坐标对象(标记) 94 mkplacemark *placemark = item.placemark; 95 /* 96 地标里存放的经纬度,以及位置的地理信息说明,如名字、街道等等 97 */ 98 //创建大头针 99 mypointannotation *annotation = [[mypointannotation alloc] initwithcoordinate:placemark.location.coordinate title:placemark.name subtitle:placemark.locality information:placemark.locality]; 100 101 //加入到地图中 102 [_mapview addannotation:annotation]; 103 } 104 105 106 }else { 107 nslog(@"搜索失败"); 108 109 } 110 111 }]; 112 113 } 114 115 //关键字搜索 116 - (void)keywordsearch { 117 //创建地理编码 118 clgeocoder *geocoder = [[clgeocoder alloc] init]; 119 //正向地理编码 120 [geocoder geocodeaddressstring:@"青岛科技大学" completionhandler:^(nsarray * _nullable placemarks, nserror * _nullable error) { 121 122 if (error == nil) { 123 //解析地理位置成功 124 //成功后遍历数组 125 for (clplacemark *place in placemarks) { 126 127 //创建大头针 128 129 mypointannotation *annotation = [[mypointannotation alloc] initwithcoordinate:place.location.coordinate title:place.name subtitle:place.locality information:place.locality]; 130 //将大头针加入到地图 131 [_mapview addannotation:annotation]; 132 133 } 134 135 }else { 136 137 nslog(@"正向地理编码解析失败"); 138 } 139 140 141 }]; 142 143 } 144 145 146 //完成更新用户定位 147 - (void)mapview:(mkmapview *)mapview didupdateuserlocation:(mkuserlocation *)userlocation { 148 149 150 _userlocationlable.text = [nsstring stringwithformat:@"用户位置: %.5f, %.5f",userlocation.coordinate.latitude, userlocation.coordinate.longitude]; 151 nslog(@"%@",_userlocationlable.text); 152 153 }
3. 自定义mypointannotation工程如下:
1 mypointannotation.h文件 2 3 #import 4 5 @interface mypointannotation : mkpointannotation 6 7 /** 大头针信息 */ 8 @property(nonatomic, copy) nsstring *information; 9 10 //构造方法 11 - (id)initwithcoordinate:(cllocationcoordinate2d)coordinate title:(nsstring *)title subtitle:(nsstring *)subtitle information:(nsstring *)information; 12 13 @end 14 15 mypointannotation.m文件 16 17 #import "mypointannotation.h" 18 19 @implementation mypointannotation 20 21 - (id)initwithcoordinate:(cllocationcoordinate2d)coordinate title:(nsstring *)title subtitle:(nsstring *)subtitle information:(nsstring *)information { 22 23 if (self = [super init]) { 24 //标题 25 self.title = title; 26 //子标题 27 self.subtitle = subtitle; 28 //坐标 29 self.coordinate = coordinate; 30 //信息 31 self.information = information; 32 } 33 return self; 34 } 35 36 @end
4. 自定义myannotationview工程如下:
1 myannotationview.h文件 2 #import 3 #import "mypointannotation.h" //导入自定义的大头针 4 @interface myannotationview : mkpinannotationview { 5 6 mypointannotation *mypointannotation; 7 8 } 9 10 //静态图片需要继承这个 11 //@interface myannotationview : mkannotationview { 12 // mypointannotation *mypointannotation; 13 //} 14 15 @end 16 17 18 myannotationview.m文件 19 #import "myannotationview.h" 20 21 @implementation myannotationview 22 23 - (instancetype)initwithannotation:(id)annotation reuseidentifier:(nsstring *)reuseidentifier { 24 if (self = [super initwithannotation:annotation reuseidentifier:reuseidentifier]) { 25 //保存参数-传过来的大头针 26 mypointannotation = annotation; 27 28 //创建图片 29 uiimage *image = [uiimage imagenamed:@"pink"]; 30 31 //这种方式只适合静态图片 ,不适合动态和拖拽动态功能,它们有冲突 需要更改一下.h文件中的继承 32 //这种方式继承mkannotationview 否则没有效果 33 // nsdata *imagedata = uiimagepngrepresentation(image); 34 // //处理imagedata 比例5 35 // image = [uiimage imagewithdata:imagedata scale:5]; 36 // //修改当前视图的大小 37 // self.frame = cgrectmake(0, 0, 40, 40); 38 // //设置图片 39 // self.image = image; 40 // //设置填充模式 按比例填满 41 // self.contentmode = uiviewcontentmodescaletofill; 42 43 44 uiimageview *imageview = [[uiimageview alloc] initwithframe:cgrectmake(-15, -5, 45, 45)]; 45 imageview.image = image; 46 [self addsubview:imageview]; 47 48 //允许气泡弹出 49 self.canshowcallout = yes; 50 //拖拽 51 self.draggable = yes; 52 //下坠动画 53 self.animatesdrop = yes; 54 55 56 uibutton *leftbutton = [uibutton buttonwithtype:uibuttontypeinfodark]; 57 [leftbutton addtarget:self action:@selector(leftbutton) forcontrolevents:uicontroleventtouchupinside]; 58 //设置左边访问view 59 self.leftcalloutaccessoryview = leftbutton; 60 61 uibutton *rightbutton = [uibutton buttonwithtype:uibuttontypecontactadd]; 62 [rightbutton addtarget:self action:@selector(rightbutton) forcontrolevents:uicontroleventtouchupinside]; 63 //设置右边访问view 64 self.rightcalloutaccessoryview = rightbutton; 65 66 } 67 return self; 68 } 69 70 71 - (void)leftbutton { 72 nslog(@"leftbutton:%@",mypointannotation.title); 73 } 74 75 - (void)rightbutton { 76 nslog(@"rightbutton:%@",mypointannotation.information); 77 } 78 79 @end