iOS系统为我们提供了原生的mapView,我们只需要将mapView控件拖动到stiryBoard中,或者用代码创建并添加到界面上,就能将地图显示出来。然后再通过实现地图的代理方法,来实现路线规划,用户位置定位,跟随用户位置等功能。下面展示的代码就是关于如何在界面上添加一个地图,并通过地图的代理方法来实现路线规划。
实现原理是我们先创建一个编码工具类,这个工具类的作用是可以用来创建起点和终点。当我们创建好起点终点后,就通过一个MKDirections类的对象将我们的起点和终点发送给服务器,苹果的服务器收到我们提供的起点和终点后会帮我们规划好一条路线,并返回给我们。这个过程中app并不参与路线规划的计算,app只是将用户输入的起点终点发送给服务器,然后由服务器来进行路线规划。这样最直接的好处是能够将路径计算的任务交给服务器,从而提高了app的性能。当然除了苹果提供的原生地图,我们也可以使用百度地图和高德地图的SDK。但要注意的是苹果地图在国内的数据供应商是高德。所以使用高德地图SDK和使用苹果原生地图数据是一样的。使用第三方地图的SDK还会产生一个问题就是会降低app的性能。运行app进行定位和路线规划的时候内存会飙升到百兆以上。但这并不是说我们不能使用第三方地图的SDK,只是具体使用那一个,需要根据我们开发中的需求来确定。第三方地图的优势在于有更丰富的功能。像百度地图和高德地图就提供了室内地图,热力图等功能。
#import "ViewController.h"
//地图的方法,需要导入地图的头文件
#import "HMAnnotation.h"
@interface ViewController ()
//编码工具
@property(strong,nonatomic)CLGeocoder *geocoder;
//用于发送请求给服务器,获取规划好后的路线。
@property(strong,nonatomic)MKDirections *directs;
//地图
@property(strong,nonatomic)MKMapView *mapView;
@end
- (void)viewDidLoad {
[super viewDidLoad];
// 创建并添加地图
MKMapView *mapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
self.mapView = mapView;
[self.view addSubview:mapView];
mapView.delegate = self;
self.geocoder = [[CLGeocoder alloc]init];
// 通过地理编码的类,创建起点和终点
[_geocoder geocodeAddressString:@"华强北" completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {
MKMapItem *item1 = [[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc]initWithPlacemark:placemarks.lastObject]];
// 添加一个大头针
// 创建一个大头针模型
HMAnnotation *anni = [[HMAnnotation alloc]init];
// 设置大头针的coordinate属性(即经纬度属性),coordinate属性类型为经纬度类型.
anni.coordinate = item1.placemark.location.coordinate;
// 将大头针添加到地图
[self.mapView addAnnotation:anni];
// 让地图显示到定位的点的附近,region表示一个范围
MKCoordinateRegion region = MKCoordinateRegionMake(item1.placemark.coordinate, MKCoordinateSpanMake(0.01, 0.01));
// 让地图只显示一个固定要显示的区域
self.mapView.region = region;
// 创建终点
[_geocoder geocodeAddressString:@"东莞" completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {
// item可以理解为点的意思,这里为了可读性,加尾缀1和2来表示
MKMapItem *item2 = [[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc]initWithPlacemark:placemarks.lastObject]];
// 添加一个大头针到终点
HMAnnotation *anni = [[HMAnnotation alloc]init];
anni.coordinate = item1.placemark.location.coordinate;
[self.mapView addAnnotation:anni];
// 调用下面自定义方法给服务器发送请求
[self requesrWithItem:item1 andItem2:item2];
}];
}];
}
-(void)requesrWithItem:(MKMapItem *)item1 andItem2:(MKMapItem *)item2
{
// 接收传入的参数,向苹果服务器发送请求
// 创建请求体,设置请求体的总店和起点
MKDirectionsRequest *requst = [[MKDirectionsRequest alloc]init];
requst.source = item1;
requst.destination = item2;
// 发送请求
self.directs = [[MKDirections alloc]initWithRequest:requst];
// 服务器计算好路径后给我们返回了数据
[self.directs calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {
// 获取所有规划的路径
NSArray *routes = response.routes;
// 获取规划路径中的的最后一条路径,如果只返回一条路径就能取到那一条
MKRoute *route = routes.lastObject;
// 定义数组保存路线中的每一步
NSArray *stepArr = route.steps;
// 遍历路线中的每一步
for (MKRouteStep *step in stepArr) {
// 打印路线的信息
NSLog(@"%f %@",step.distance,step.instructions);
// 绘制遮盖打印到地图上,绘制方法的实现在下面
[self.mapView addOverlay:step.polyline];
}
}];
}
// 返回指定的遮盖模型所对应的遮盖视图, renderer-渲染
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay
{
// 判断类型是不是MKOverlay类型
if ([overlay isKindOfClass:[MKPolyline class]]) {
// 针对线段,系统有提供好的遮盖样式
MKPolylineRenderer *render = [[MKPolylineRenderer alloc]initWithOverlay:overlay];
// 配置渲染的宽度和渲染的颜色
render.lineWidth = 5;
render.strokeColor = [UIColor redColor];
// 返回配置好的渲染
return render;
}
// 否则返回nil
return nil;
}
这篇文章针对的是掌握iOS中掌握UI基本使用方法,还有能理解OC面向对象的概念的开发者。如果你还没掌握上面的内容,那看不懂代码和文章内容是正常的现象。如果能看懂但对于文章里面的一个类还不能很好地理解,可以去查看苹果的官方文档。在官方文档里对于各个类的介绍和使用都有详细的说明。如果想看代码的运行效果,可以将代码拷贝到一个新建项目的ViewController.m文件中,运行后就能看到效果。
这个demo已经上传到git上面了。下面是链接地址,点击链接地址再点击downLoadZIP就可以下载整个文件。直接运行就可以看到效果了。
项目地址
网友评论
这个是demo的链接地址,文章里面也添加了。