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

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