运行效果:

          

一.利用<CoreLocation/CoreLocation.h>定位

创建变量 CLLocationManager *locationManager ,并加入<CLLocationManagerDelegate>协议

以下是Viewdidload里需要初始化的参数:

    self.locationManager = [[CLLocationManager alloc]init];
[self.locationManager setDelegate:self];
[self.locationManager requestAlwaysAuthorization];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];

开始定位后,结果会用过这个函数回调,locations数组含有一切定位信息:时间,经纬度等

// Location Manager Delegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"%@", [locations lastObject]);
}

需要注意的是:在iOS8之后,使用地图需要请求权限,需要在info.plist文件中加入2个字段:

NSLocationWhenInUseDescription

NSLocationAlwaysUsageDescription

并且在使用定位前需要运行函数:

 [self.locationManager requestAlwaysAuthorization];
或 [locationManager requestWhenInUseAuthorization];

二、 利用Mapkit使用地图服务

创建变量 MKMapView *regionMapView ,并加入<MKMapViewDelegate>协议

初始化参数:

self.regionMapView.delegate = self;
self.regionMapView.showsUserLocation = YES;

关于地图,有个大坑是目前各大地图的坐标系都不一样。

国际标准是WGS-84,比如谷歌、苹果地图提供的API等都是基于这个坐标的。

天朝为了“照顾大家安全”,立了个新标准GCJ-02,比如高德地图就是基于它的。也就是所谓的火星坐标系。另外百度为了"更好地保护大家隐私",也有自己的二次加密后的标准BD-09.

如果直接使用国外那些不安全的地图提供的经纬度来插到我们天朝地图上,很可能就存在很大偏移。所以作为地图开发者我们首先要熟练运用6种坐标互相转换算法。

国外《-》高德  高德《-》百度    百度《-》国外

所以上面利用CoreLocation定位出的经纬度显示是有偏差的(定位出的是WGC-84,国内目前是高德地图),要想正确显示就要用算法转换(WGC-84转GCJ-02)。

或者有另外一个方法,利用MapKit的回调函数,得到的结果是经过转换的。可见MapKit内部应该是已经调用了定位的。

#pragma mark MKMapViewDelegate -user location定位变化
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
_userlocation=userLocation;
self.nowCoords = [userLocation coordinate];
NSLog(@"定位到当前位置");
_updateInt++;
//放大地图到自身的经纬度位置。
self.userRegion = MKCoordinateRegionMakeWithDistance(self.nowCoords, , );
if(_updateInt==||_iffollowed==YES){
[self.regionMapView setRegion:self.userRegion animated:NO];
}
//仅在打开地图后,第一次更新地理信息时,确定使用者的大致地理位置
if (_updateInt<=) {
//CLGeocoder 是谷歌接口通过经纬度查询大致地址
NSLog(@"通过经纬度查询地理信息");
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:[userLocation location] completionHandler:^(NSArray *array, NSError *error) {
if (array.count > ) {
CLPlacemark *placemark = [array objectAtIndex:];
_myregion=[placemark region];
NSString *region = [placemark.addressDictionary objectForKey:@"SubLocality"];
NSString *address = [placemark.addressDictionary objectForKey:@"Name"];
self.regionStr = region;
self.addressStr = address;
self.city = placemark.locality;
NSLog(@"当前使用者所在:地点名:%@,地址:%@,城市:%@",self.regionStr,self.addressStr,self.city);
}else{
self.regionStr = @"";
self.addressStr = @"";
self.city = @"";
NSLog(@"未查询到有效地址");
}
}];
}
//判断是否是否要根据运动路线绘图
if (![[NSString stringWithFormat:@"%0.8f",[[userLocation location] coordinate].latitude] isEqualToString:[NSString stringWithFormat:@"%0.8f",self.centerCoordinate.latitude]] ) { //做点什么
return;
}
}

使用地图主要有2个基本:(1)地理编码:地址转经纬度。

             (2)地理反编码:经纬度转成地址。

(1)地址转经纬度的方法(具体功能为:输入查找地点,然后显示在地图上)

    方法有2个:一个是采用MK框架自带的接口 CLGeocoder,该接口还有其他的用法,按住CMD+点击CLGeocoder就会出现该类的接口。

CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:@"屏峰" completionHandler:^(NSArray *placemarks, NSError *error) {
if ([placemarks count] > && error == nil){
NSLog(@"Found %lu placemark(s).", (unsigned long)[placemarks count]);
CLPlacemark *firstPlacemark = [placemarks objectAtIndex:];
NSLog(@"Longitude = %f", firstPlacemark.location.coordinate.longitude);
NSLog(@"Latitude = %f", firstPlacemark.location.coordinate.latitude);
}
else if ([placemarks count] == && error == nil){
NSLog(@"Found no placemarks.");
}
else if (error != nil){
NSLog(@"An error occurred = %@", error);
}
}];

  另一种就是使用百度或者其他地图的接口,比如我的Demo中使用的就是百度接口,不方便的是,百度接口获得的经纬度需要转换才能正确的“插”在高德上。

百度接口为:http://api.map.baidu.com/place/search?&query=西湖&region=杭州&output=json&key=bqApldE1oh6oBb98VYyIfy9S

主要是4个参数。效果如下:

 (2)地理反编码:经纬度转成地址。

方法同上,反过来也有接口。

    第一种是Mapkit接口:

CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:[userLocation location] completionHandler:^(NSArray *array, NSError *error) {
if (array.count > ) {
CLPlacemark *placemark = [array objectAtIndex:];
_myregion=[placemark region];
NSString *region = [placemark.addressDictionary objectForKey:@"SubLocality"];
NSString *address = [placemark.addressDictionary objectForKey:@"Name"];
self.regionStr = region;
self.addressStr = address;
self.city = placemark.locality;
NSLog(@"当前使用者所在:地点名:%@,地址:%@,城市:%@",self.regionStr,self.addressStr,self.city);
}else{
self.regionStr = @"";
self.addressStr = @"";
self.city = @"";
NSLog(@"未查询到有效地址");
}
}];

第二种是其他接口,同样传入参数是经纬度,返回地理信息。

比如百度:http://api.map.baidu.com/geocoder/v2/?ak=E4805d16520de693a3fe707cdc962045&callback=renderReverse&location=39.983424,116.322987&output=json&pois=1

效果:

三、地图操作:

1.地图依据经纬度插点:

主要利用Mapkit接口:(如果要发现某个类有哪些好玩的接口可以按住CMD+该类名进去看看有哪些函数,然后去搜搜这些函数的用法或看看官方文档)

    [map addAnnotation:annotation];

后者,也就是那个棒棒糖属于MKAnnotation类,这个类有很多自定义UI的例子,通过在上面加label,加button,可以扩展获得很多功能。(比如显示该地点的具体图片文字信息等)

2.地图画线进行导航:

这些奇葩的功能都是由你所使用的地图API提供的,我这里使用的Mapkit,所以我使用的就是Mapkit的画线接口。

另外神奇的是,你可以通过[UIApplication sharedApplication]使用其他地图来构造导航路线。

(1)把导航的繁重任务交给其他专业的地图吧,这里只是大概代码(具体参见我的DEMO):

-(void)doAcSheet{
NSArray *appListArr = [CheckInstalledMapAPP checkHasOwnApp];
NSString *sheetTitle = [NSString stringWithFormat:@"导航到 %@",[self.navDic objectForKey:@"address"]];
UIActionSheet *sheet;
if ([appListArr count] == ) {
sheet = [[UIActionSheet alloc] initWithTitle:sheetTitle delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:appListArr[],appListArr[], nil];
}else if ([appListArr count] == ){
sheet = [[UIActionSheet alloc] initWithTitle:sheetTitle delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:appListArr[],appListArr[],appListArr[], nil];
}else if ([appListArr count] == ){
sheet = [[UIActionSheet alloc] initWithTitle:sheetTitle delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:appListArr[],appListArr[],appListArr[],appListArr[], nil];
}else if ([appListArr count] == ){
sheet = [[UIActionSheet alloc] initWithTitle:sheetTitle delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:appListArr[],appListArr[],appListArr[],appListArr[],appListArr[], nil];
}
sheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[sheet showInView:self.view];
} -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
NSString *btnTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if (buttonIndex == ) {
CLLocationCoordinate2D to;
to.latitude = _naviCoordsGd.latitude;
to.longitude = _naviCoordsGd.longitude;
MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:to addressDictionary:nil]]; toLocation.name = _addressStr;
[MKMapItem openMapsWithItems:[NSArray arrayWithObjects:currentLocation, toLocation, nil] launchOptions:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:MKLaunchOptionsDirectionsModeDriving, [NSNumber numberWithBool:YES], nil] forKeys:[NSArray arrayWithObjects:MKLaunchOptionsDirectionsModeKey, MKLaunchOptionsShowsTrafficKey, nil]]];
}
if ([btnTitle isEqualToString:@"google地图"]) {
NSString *urlStr = [NSString stringWithFormat:@"comgooglemaps://?saddr=%.8f,%.8f&daddr=%.8f,%.8f&directionsmode=transit",self.nowCoords.latitude,self.nowCoords.longitude,self.naviCoordsGd.latitude,self.naviCoordsGd.longitude];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlStr]];
}else if ([btnTitle isEqualToString:@"高德地图"]){
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"iosamap://navi?sourceApplication=broker&backScheme=openbroker2&poiname=%@&poiid=BGVIS&lat=%.8f&lon=%.8f&dev=1&style=2",self.addressStr,self.naviCoordsGd.latitude,self.naviCoordsGd.longitude]];
[[UIApplication sharedApplication] openURL:url]; }else if ([btnTitle isEqualToString:@"百度地图"]){
double bdNowLat,bdNowLon;
bd_encrypt(self.nowCoords.latitude, self.nowCoords.longitude, &bdNowLat, &bdNowLon); NSString *stringURL = [NSString stringWithFormat:@"baidumap://map/direction?origin=%.8f,%.8f&destination=%.8f,%.8f&&mode=driving",bdNowLat,bdNowLon,self.naviCoordsBd.latitude,self.naviCoordsBd.longitude];
NSURL *url = [NSURL URLWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
}else if ([btnTitle isEqualToString:@"显示路线"]){
[self drawRout];
}
}

(2)还是试试自己画线好了O(∩_∩)O:(主要是提供两个点的参数)

-(void)drawRout{
MKPlacemark *fromPlacemark = [[MKPlacemark alloc] initWithCoordinate:_nowCoords addressDictionary:nil];
MKPlacemark *toPlacemark = [[MKPlacemark alloc] initWithCoordinate:_naviCoordsGd addressDictionary:nil];
MKMapItem *fromItem = [[MKMapItem alloc] initWithPlacemark:fromPlacemark];
MKMapItem *toItem = [[MKMapItem alloc] initWithPlacemark:toPlacemark]; [self.regionMapView removeOverlays:self.regionMapView.overlays];
[self findDirectionsFrom:fromItem to:toItem]; }
#pragma mark - ios7路线绘制方法
-(void)findDirectionsFrom:(MKMapItem *)from to:(MKMapItem *)to{
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
request.source = from;
request.destination = to;
request.transportType = MKDirectionsTransportTypeWalking;
if (ISIOS7) {
request.requestsAlternateRoutes = YES;
} MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
//ios7获取绘制路线的路径方法
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (error) {
NSLog(@"error:%@", error);
}
else {
MKRoute *route = response.routes[];
[self.regionMapView addOverlay:route.polyline];
}
}];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView
rendererForOverlay:(id<MKOverlay>)overlay{
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
renderer.lineWidth = 5.0;
renderer.strokeColor = [UIColor redColor];
return renderer;
}

GithubDemo:https://github.com/rayshen/ShenMapViewDemo

[iOS 利用MapKit和CoreLocation框架打造精简的定位和导航]的更多相关文章

  1. ios开发-MapKit(地图框架)使用简介

    我们使用app的时候,很多软件都自带了地图功能.我们可以看到自己的位置,看到周围商场等信息.我们也可以导航,划线等. 其实苹果的MapKit使用起来还是很简单的.这里简单的介绍一下. 0.使用前准备 ...

  2. iOS:地图:MapKit和CoreLocation

    地图:MapKit和CoreLocation 简介: 现在很多的社交软件都引入了地图和定位功能,要想实现这2大功能,那就不得不学习其中的2个框架:MaKit和CoreLocation CoreLoca ...

  3. 【高德API】如何利用MapKit开发全英文检索的iOS地图

    原文:[高德API]如何利用MapKit开发全英文检索的iOS地图 制作全英文地图的展示并不困难,但是要制作全英文的数据检索列表,全英文的信息窗口,你就没办法了吧.告诉你,我有妙招!使用iOS自带的M ...

  4. MapKit/CoreLocation框架 总结

    MapKit/CoreLocation框架 /*英译 core:核心 track:踪迹 current:当前 statellite:卫星 hybird:混合  region:范围 annotation ...

  5. 利用 Dijit 组件框架打造丰富的用户界面

    原文出处:Joe Lennon 从头开始学习 Dojo,第 3 部分 利用 Dijit 组件框架打造丰富的用户界面 Dijit 是什么? Dijit 是 Dojo 工具包的富组件用户界面库.这些组件完 ...

  6. IOS CoreLocation框架的使用(用于地理定位)

    ●  在移动互联网时代,移动app能解决用户的很多生活琐事,比如 ●  导航:去任意陌生的地方 ●  周边:找餐馆.找酒店.找银行.找电影院 ●  在上述应用中,都用到了地图和定位功能,在iOS开发中 ...

  7. iOS地图----MapKit框架

    1.MapKit框架使用前提 ①导入框架 ②导入主头文件 #import <MapKit/MapKit.h> ③MapKit框架使用须知 MapKit框架中所有数据类型的前缀都是MK Ma ...

  8. iOS定位--CoreLocation框架

    CoreLocation框架的使用 // 首先导入头文件 #import <CoreLocation/CoreLocation.h> CoreLocation框架中所有数据类型的前缀都是C ...

  9. CoreLocation框架的使用

    CoreLocation框架使用 一.地图和定位的简介 1.应用场景 周边:找餐馆/找KTV/找电影院(团购APP) 导航:根据用户设定的起点和终点,进行路线规划,并指引用户如何到达(地图APP) 2 ...

随机推荐

  1. noi题库(noi.openjudge.cn) 1.8编程基础之多维数组T01——T10

    T01 矩阵交换行 描述 给定一个5*5的矩阵(数学上,一个r×c的矩阵是一个由r行c列元素排列成的矩形阵列),将第n行和第m行交换,输出交换后的结果. 输入 输入共6行,前5行为矩阵的每一行元素,元 ...

  2. express:webpack dev-server中如何将对后端的http请求转到https的后端服务器中?

    在上一篇文章(Webpack系列:在Webpack+Vue开发中如何调用tomcat的后端服务器的接口?)我们介绍了如何将对于webpack-dev-server的数据请求转发到后端服务器上,这在大部 ...

  3. 如何在 Apache 中为你的网站设置404页面

    一个好的网站,拥有一个好的 404页面 是标配. 为何要有 404页面?如何设置一个 404页面? why 404 pages? 在本地,比如我打开 localhost/fuck.htm(该文件不存在 ...

  4. 高性能JavaScript 重排与重绘

    先回顾下前文高性能JavaScript DOM编程,主要提了两点优化,一是尽量减少DOM的访问,而把运算放在ECMAScript这一端,二是尽量缓存局部变量,比如length等等,最后介绍了两个新的A ...

  5. 安装laravel5.1项目命令

    作为程序员还有什么比命令行执行效率还要快的呢,哈哈... composer create-project laravel/laravel your-project-name --prefer-dist ...

  6. 解决nf_conntrack: table full, dropping packet问题

    " > /proc/sys/net/nf_conntrack_max iptables -t raw -A PREROUTING -p tcp -m tcp --dport -j NO ...

  7. versionCompare 版本号比较工具

    简介 需求非常简单,需要比较软件或app的版本号,判断大小,形如 0.10.2形式的版本号字符串.实现逻辑是按照点(.)分割字符串,然后逐级比较版本大小.不存在的按0处理,空字符串小于非空字符串. 测 ...

  8. 用 canvas 做个好玩的网站背景

    不知不觉又好久没更过博客了,老调新弹一下,之前做的一个小效果,觉得蛮有意思的,也有朋友问是怎么做的,就分享一下,写个博文吧. 先上demo吧:http://whxaxes.github.io/canv ...

  9. python基础-基本数据类型总结_整型(int)_字符型(str)_day3

     一.基本数据类型 1.整型(int) ps1:数字 int ,所有的功能,都放在int里a1 = 123a1 = 456 ps2: int 将字符串转换为数字 # -int # 将字符串转换为数字 ...

  10. Beta--项目冲刺第六天

    胜利在望-- 队伍:F4 成员:031302301 毕容甲 031302302 蔡逸轩 031302430 肖阳 031302418 黄彦宁 会议内容: 1.站立式会议照片: 2.项目燃尽图 3.冲刺 ...