调用地图功能的实现

一:苹果自带地图

   学习如逆水行舟,不进则退。古人告诉我们要不断的反思和总结,日思则日精,月思则月精,年思则年精。只有不断的尝试和总结,才能让我们的工作和生活更加 轻松愉快和美好。连着做了两个大的商城外包项目,智慧城市,搜牧通,花费了近四个月的时间,终于在反复修改后完美收工。期间的困难自不必说,以后多多总结 和沟通吧。百度地图的使用之前已经发表了一篇文章,说的很详细了,这里不再涉及,言归正传,我们说一下如何调用苹果自带的地图

  第一步:导入地图文件  #import <MapKit/MapKit.h>

  第二步:获取当前位置和目的地的经纬度,然后打开地图即可

  

  //获取当前位置

1 MKMapItem *mylocation = [MKMapItem mapItemForCurrentLocation];

//当前经维度

1     float currentLatitude=mylocation.placemark.location.coordinate.latitude;
2
3 float currentLongitude=mylocation.placemark.location.coordinate.longitude;
4
5
6
7 CLLocationCoordinate2D coords1 = CLLocationCoordinate2DMake(currentLatitude,currentLongitude);

//目的地位置

 1 coordinate.latitude=[[dataSource objectForKey:@"lat"] floatValue];
2
3 coordinate.longitude=[[dataSource objectForKey:@"lng"] floatValue];
4
5
6
7
8
9 CLLocationCoordinate2D coords2 = coordinate;
10
11
12
13 // ios6以下,调用google map
14
15 if (SYSTEM_VERSION_LESS_THAN(@"6.0"))
16
17 {
18
19 NSString *urlString = [[NSString alloc] initWithFormat:@"http://maps.google.com/maps?saddr=%f,%f&daddr=%f,%f&dirfl=d", coords1.latitude,coords1.longitude,coords2.latitude,coords2.longitude];
20
21 NSURL *aURL = [NSURL URLWithString:urlString];
22
23 //打开网页google地图
24
25 [[UIApplication sharedApplication] openURL:aURL];
26
27 }
28
29 else
30
31 // 直接调用ios自己带的apple map
32
33 {
34
35 //当前的位置
36
37 MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];
38
39 //起点
40
41 //MKMapItem *currentLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:coords1 addressDictionary:nil]];
42
43 //目的地的位置
44
45 MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:coords2 addressDictionary:nil]];
46
47
48
49 toLocation.name = @"目的地";
50
51 NSString *myname=[dataSource objectForKey:@"name"];
52
53 if (![XtomFunction xfunc_check_strEmpty:myname])
54
55 {
56
57 toLocation.name =myname;
58
59 }
60
61
62
63 NSArray *items = [NSArray arrayWithObjects:currentLocation, toLocation, nil];
64
65 NSDictionary *options = @{ MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsMapTypeKey: [NSNumber numberWithInteger:MKMapTypeStandard], MKLaunchOptionsShowsTrafficKey:@YES };
66
67 //打开苹果自身地图应用,并呈现特定的item
68
69 [MKMapItem openMapsWithItems:items launchOptions:options];
70
71 }
72
73   

  通过这两步就可以轻松的开启苹果自带地图导航,感觉真是挺不错的,唯一的缺点是开启地图获取路线信息耗费的手机流量比较大,最好在wifi条件下调用。如果不是必须,尽量还是用高德或者百度自带的地图就好。

二:百度地图

一:首先我们有一点与用googlemap开发的不同,需要创建BMKMapManager管理应用程序的map,如果没有这个类,地图则不能够显示。

下面红色的字体是自己在百度官方申请的地图api——key;

1 BMKMapManager  *_mapManager = [[BMKMapManager alloc] init];
2
3 BOOL ret = [_mapManager start:@"C3252C69EDB6D21A10B3FC9657FD1DDC7E0000**"generalDelegate:self];
4
5 if (!ret) {
6
7 NSLog(@"manager start failed!");
8
9 }

二:在view中添加BMKMapView,同时设置BMKMapViewDelegate,添加annotation(记录兴趣点,BMKAnnotation),同时每个兴趣点可以设置其title(设置annotation的标题),以及subtitle(子标题)。

 1 @interface MapBaiDu : UIViewController <BMKMapViewDelegate> {  }
2
3 @property (nonatomic, strong) BMKMapView *_mapView;
4
5 @end
6
7
8 - (void)viewDidLoad {
9
10
11
12 _mapView = [[BMKMapView alloc] initWithFrame:CGRectMake(0, 39, 320, 377)]; //创建MKMapView
13
14 [self.view addSubview:_mapView];
15
16 [_mapView release];
17
18
19
20 _mapView.delegate = self; //设置代理
21
22 _mapView.showsUserLocation = YES; //设置为可以显示用户位置
23
24 CLLocationCoordinate2D coordinate; //设定经纬度
25
26 coordinate.latitude = 40.027283; //纬度
27
28 coordinate.longitude = 116.313217; //经度
29
30
31
32 BMKCoordinateRegion viewRegion = BMKCoordinateRegionMake(coordinate, BMKCoordinateSpanMake(1.0,1.0));
33
34 BMKCoordinateRegion adjustedRegion = [_mapView regionThatFits:viewRegion];
35
36 [_mapView setRegion:adjustedRegion animated:YES];
37
38 }

上 面最后一行  :设置当前地图的经纬度范围,设定的该范围可能会被调整为适合地图窗口显示的范围。region是BMKMapView的一个属性,类型BMKCoordinateRegion ,这行的意思是创建一个以coordinate为中心,上下左右个0.5个经(纬)度。但是这时我们需要注意一个问题就是,创建的区域是一个正方形,并不 符合我们所需要的BMKMapView比例;之后用方法regionThatFits调整显示范围。

 1 ///表示一个经纬度区域
2
3 typedef struct {
4
5 CLLocationCoordinate2D center; ///< 中心点经纬度坐标
6
7 BMKCoordinateSpan span; ///< 经纬度范围
8
9 } BMKCoordinateRegion;
10
11
12
13
14
15 ///表示一个经纬度范围
16
17 typedef struct {
18
19 CLLocationDegrees latitudeDelta; ///< 纬度范围
20
21 CLLocationDegrees longitudeDelta; ///< 经度范围
22
23 } BMKCoordinateSpan;

三:下面我们简单说一下delegate

1:地图区域改变时候调用函数:

1 - (void)mapView:(BMKMapView *)mapView regionWillChangeAnimated:(BOOL)animated;

- (void)mapView:(BMKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;

2:annotation

*根据anntation生成对应的View

- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id<BMKAnnotation>)annotation;

*当mapView新添加annotation views时,调用此接口

- (void)mapView:(BMKMapView *)mapView didAddAnnotationViews:(NSArray *)views;

*当选中一个annotation views时,调用此接口

- (void)mapView:(BMKMapView *)mapView didSelectAnnotationView:(BMKAnnotationView *)view;

*当取消选中一个annotation views时,调用此接口

- (void)mapView:(BMKMapView *)mapView didDeselectAnnotationView:(BMKAnnotationView *)view;

而annotation分为两部分:BMKAnotation该类为标注点的protocol,提供了标注类的基本信息函数,title和subtitle分别是标题和子标题;同时可以设置标注的左边,在拖曳时候会被调用setCoordinate;

BMKAnnotationView为标注点显示视图类,该类继承UIView,可以设置此view显示的图像,可以设置centerOffset(中心的位置,正的偏移使view超右下方 移动,负的朝右上方移动,单位为像素),还可以设置calloutOffset改变淡出的气泡位置(正的偏移使view超右下方移动,负的朝左上方移动, 单位是像素)。还可以设置其触摸事件,默认情况下为YES,可以选中,也可以是enabled =  NO。其他的属性还 有:selected,canShowCallout,leftCalloutAccessoryView,rightCalloutAccessoryView。 等等

四:当地图view定位时调用函数:

*当取消选中一个annotation views时,调用此接口

- (void)mapView:(BMKMapView *)mapView didDeselectAnnotationView:(BMKAnnotationView *)view;

*在地图View将要启动定位时,会调用此函数

- (void)mapViewWillStartLocatingUser:(BMKMapView *)mapView;

*在地图View停止定位后,会调用此函数

- (void)mapViewDidStopLocatingUser:(BMKMapView *)mapView;

*定位失败后,会调用此函数

- (void)mapView:(BMKMapView *)mapView didFailToLocateUserWithError:(NSError *)error;

*用户位置更新后,会调用此函数

- (void)mapView:(BMKMapView *)mapView didUpdateUserLocation:(BMKUserLocation *)userLocation;

五:当有overlay(阴影标示某一个区域)生成或者新添加的时候调用此接口

*根据overlay生成对应的View

- (BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id <BMKOverlay>)overlay;

*当mapView新添加overlay views时,调用此接口

- (void)mapView:(BMKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews;

六:当点击annotation view弹出的泡泡时,调用此接口

*当点击annotation view弹出的泡泡时,调用此接口

- (void)mapView:(BMKMapView *)mapView annotationViewForBubble:(BMKAnnotationView *)view;

九:annotation view有许多不同的状态,在不同状态的时候我们都可以设置不同的操作,拖动annotation view时view的状态变化

 1 - (void)mapView:(BMKMapView *)mapView annotationView:(BMKAnnotationView *)view didChangeDragState:(BMKAnnotationViewDragState)newState
2
3 fromOldState:(BMKAnnotationViewDragState)oldState;
4
5
6
7
8
9 enum {
10
11 BMKAnnotationViewDragStateNone = 0, ///< 静止状态.
12
13 BMKAnnotationViewDragStateStarting, ///< 开始拖动
14
15 BMKAnnotationViewDragStateDragging, ///< 拖动中
16
17 BMKAnnotationViewDragStateCanceling, ///< 取消拖动
18
19 BMKAnnotationViewDragStateEnding ///< 拖动结束
20
21 };
22
23
24
25 typedef NSUInteger BMKAnnotationViewDragState;

三:高德地图

之前工作在一家智能设备的公司,做过一个亲友定位监控系统,类似现在比较流行的360儿童手环。所以这里简单介绍定位与地图。

1 定位服务

iOS设备提供三种不同定位途径,蜂窝式移动电话基站定位;WiFi定 位,通过查询一个WiFi路由器的地理位置信息,比较省电;GPS卫星定位,通过3~4颗卫星定位,最为准确,但是耗电量大。iOS系统如果能够接收 GPS信息,那么设备优先采用GPS,其次是WiFi,最后是基站,开发人员不能选择哪种定位方式。

定位服务使用CoreLocation框架,主要使用CLLocationMananger、 CLLocationManangerDelegate和CLLocation三个类,CLLocationMananger是定位服务管理类,获取设备 的位置信息,CLLocationManangerDelegate是代理协议,CLLocation封装了位置信息。

这里要注意,CLLocationManangerDelegate 的locationManager:didUpdateToLocation:fromLocation:方法得到的坐标是火星坐标,这个原因你懂得,所 以需要转换成真实的地理坐标。我使用的是一个第三方的CSqlite类,有一个转换坐标的数据库,你调用就可以转换为正确坐标了。

得到经纬度后,要进行地理位置信息反编码,使用CLGeocoder类实现,将地理坐标转换为地理文字描述信息,这些文字描述信息被封装在CLPlacemark类中。

当然给定地理信息的文字描述,也可以进行地理信息编码查询,转换为地理坐标,也是采用CLGeocoder类。

判断一个坐标点是否在一个无规则的多边形内

 1 //    在范围内返回1,不在返回0
2 -(int)mutableBoundConrtolAction:(NSMutableArray *)arrSome:(CLLocationCoordinate2D )myCoordinate4{
3 int n=arrSome.count;
4 float vertx[n];
5 float verty[n];
6 for (int i=0; i<arrSome.count; i++) {
7 //MyPoint类存储的是经度和纬度
8 vertx[i]=((MyPoint *)(arrSome[i])).x;
9 verty[i]=((MyPoint *)(arrSome[i])).y;
10 }
11 if (arrSome.count==0) {
12
13 return 1;
14 }
15 BOOL i=pnpoly(arrSome.count, vertx, verty, myCoordinate4.latitude, myCoordinate4.longitude);
16
17
18 if (i) {
19 return 1;
20 }else{
21 return 0;
22 }
23
24
25 return 1;
26 }
27 //多边形由边界的坐标点所构成的数组组成,参数格式 该数组的count, 多边形边界点x坐标 的组成的数组,多边形边界点y坐标 的组成的数组,需要判断的点的x坐标,需要判断的点的y坐标
28 BOOL pnpoly (int nvert, float *vertx, float *verty, float testx, float testy) {
29 int i, j;
30 BOOL c=NO;
31 for (i = 0, j = nvert-1; i < nvert; j = i++) {
32
33 if ( ( (verty[i]>testy) != (verty[j]>testy) ) &&
34 (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
35 c = !c;
36 }
37 return c;
38 }

2 系统地图

地图我目前用过系统、百度以及高德,开发人员使用都是差不多的,下面的代码涉及的类都是高德地图api提供的类。

我之前做项目,使用高德地图,做到后期,项目会出现闪退,后来查出是地图区域内存的问题,然后重新布局了地图区域,使得每一个地图区域能够及时销毁,虽然闪退周期明显延长,但是还是存在,这里不知道是何原因,说来惭愧。

设置地图区域

1 -(void)SetMapRegion:(CLLocationCoordinate2D)myCoordinate
2 {
3 MACoordinateRegion theRegion = { {0.0, 0.0 }, { 0.0, 0.0 } };
4 theRegion.center=myCoordinate;
5 [self.m_map setScrollEnabled:YES];
6 theRegion.span.longitudeDelta = 0.01f;
7 theRegion.span.latitudeDelta = 0.01f;
8 [self.m_map setRegion:theRegion animated:YES];
9 }

平移地图,上下左右

 1 -(void)panMap:(NSString *)direction{
2 CLLocationCoordinate2D changeCoordinate=self.m_map.centerCoordinate;
3 CGPoint changePoint=[self.m_map convertCoordinate:changeCoordinate toPointToView:self.m_map];
4
5 if ([direction isEqualToString:@"up"]) {
6 changePoint.y=changePoint.y+50;
7
8 }else if ([direction isEqualToString:@"down"]) {
9 changePoint.y=changePoint.y-50;
10 }else if ([direction isEqualToString:@"left"]) {
11 changePoint.x=changePoint.x-50;
12 }else if ([direction isEqualToString:@"right"]) {
13 changePoint.x=changePoint.x+50;
14 }
15 changeCoordinate=[self.m_map convertPoint:changePoint toCoordinateFromView:self.m_map];
16 [self.m_map setCenterCoordinate:changeCoordinate animated:YES];
17 }

判断某一个坐标点是否在当前地图区域内

 1 -(void)isAtCurrentRegion:(CLLocationCoordinate2D)coordiante{
2
3 CGPoint point=[self.m_map convertCoordinate:coordiante toPointToView:self.view];
4 if ((point.x<0)||(point.y<0)||(point.x>WScreen)||(point.y>HScreen)) {
5 // 如果不在 设置该点为地图中心点
6 [self SetMapRegion:coordiante];
7 }
8
9
10 }

在地图上添加标注

系统地图使用MapKit框架,核心是MKMapView类,显示地图只要添加MKMapView实例就可以了。如果要实现在地图上添加标注点, 第以是触发添加动作,第二实现MKMapViewDelegate的mapView:viewForAnnotation:完成添加标注。

高德地图实现的原理也是一样的,高德地图使用的是MAMapKit框架。 对于annotation,一般会自定义一个继承NSobject并且实现了maannotation协议的类,然后使用mapview的addAnnotation:方法就可以。MKReverseGeocoder类可以实现coordinate的反编码,这里需要实现它的代理,把得到的 地理文字描述信息赋给annotation。这里需要实现代理的mapView:viewForAnnotation:方法,一个标注其实就是一个MAAnnotationView,标注有点类似tableviewcell,这里也有重用机制。实现代理的mapView:annotationView:calloutAccessoryControlTapped:方法可以响应leftCalloutAccessoryView或者rightCalloutAccessoryView的点击事件,不过这个accessory  view必须继承自UIControl。

在地图上绘制线条和多边形

MAPolyline类定义一个由多个点相连的多段线,点与点之间尾部想 连但第一点与最后一个点不相连, 通常MAPolyline是MAPolylineView的model,它提供了两个方法polylineWithPoints:count:、polylineWithCoordinates:count:用来添加线条,然后再通过map  view的addOverlay:方法把Polyline实例添加进去,最后实现mapviewdelegate的mapView:viewForOverlay:方法就可以了。注意如果一开始添加的不是coordinate,而是point,可以通过map  view的convertPoint:toCoordinateFromView:方法进行转换。

MAPolygon类定义的就是一个不规则的由多个点组成的闭合多边形, 点与点之间按顺序尾部相连, 第一个点与最后一个点相连, 通常MAPolygon是MAPolygonView的model,首先需要添加坐标点的数组,可以使用polygonWithCoordinates:count:方法或者polygonWithPoints:count:方法,然后把这个polygon通过addOverlay:方法添加到map  view上就可以了。然后可以在mapviewdelegate里面的mapView:viewForOverlay:方法里面给MAPolygonView的属性赋值,这样一个完整的多边形就出来了。

不管是高德地图还是百度地图等第三方,都会有一个mapsearchkit,这是一个用于查询的框架,有兴趣的朋友可以多加研究。

注:作为一个iOS开发者,其实如果可以的话你可以学会使用者三种方式,但是一般我们没有比较,除非你确实闲的蛋疼,

以后在公司中,我们一半都只会使用一种,所以作为一个合格的程序员,我们应该非常熟悉的使用其中的一种,这里比较推荐百度和苹果自带的,当你狠熟悉的使用这一种之后,另外两种学起来就很简单了,

当然,对于两外两种我们也应该有个大志的了解就可以,具体使用哪个看公司。

如果想要更深入的学习与研究请查看相应的官方实例代码和API

iOS开发——高级技术&调用地图功能的实现的更多相关文章

  1. iOS开发——高级技术OC篇&运行时(Runtime)机制

    运行时(Runtime)机制 本文将会以笔者个人的小小研究为例总结一下关于iOS开发中运行时的使用和常用方法的介绍,关于跟多运行时相关技术请查看笔者之前写的运行时高级用法及相关语法或者查看响应官方文档 ...

  2. iOS开发——高级技术精选OC篇&Runtime之字典转模型实战

    Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://w ...

  3. iOS开发——高级技术&广告服务

    广告服务 上 面也提到做iOS开发另一收益来源就是广告,在iOS上有很多广告服务可以集成,使用比较多的就是苹果的iAd.谷歌的Admob,下面简单演示一下如何 使用iAd来集成广告.使用iAd集成广告 ...

  4. iOS开发——高级技术&内购服务

    内购服务 大家都知道做iOS开发本身的收入有三种来源:出售应用.内购和广告.国内用户通常很少直接 购买应用,因此对于开发者而言(特别是个人开发者),内购和广告收入就成了主要的收入来源.内购营销模式,通 ...

  5. iOS开发——高级技术&签名机制

    签名机制 最近看了objc.io上第17期中的文章 <Inside Code Signing> 对应的中文翻译版 <代码签名探析> ,受益颇深,对iOS代码签名机制有了进一步的 ...

  6. iOS开发——高级技术&摇一摇功能的实现

    摇一摇功能的实现 在AppStore中多样化功能越来越多的被使用了,所以今天就开始介绍一些iOS开发的比较实用,但是我们接触的比较少的功能,我们先从摇一摇功能开始 在 UIResponder中存在这么 ...

  7. iOS开发——高级技术&地图功能的实现

    地图功能的实现 因为有个项目要在地图中显示位置,所以用到了MapKit. 记录下来,以免以后忘记. 加入MapKit library 首先得在项目中加入MapKit,如图 MapView 先增加一个V ...

  8. iOS开发——高级技术&蓝牙服务

    蓝牙服务 蓝牙 随着蓝牙低功耗技术BLE(Bluetooth Low Energy)的发展,蓝牙技术正在一步步成熟,如今的大部分移动设备都配备有蓝牙4.0,相比之前的蓝牙技术耗电量大大降低.从iOS的 ...

  9. iOS开发——高级技术&通讯录服务

    通讯录服务 AddressBook iOS中带有一 个Contacts应用程序来管理联系人,但是有些时候我们希望自己的应用能够访问或者修改这些信息,这个时候就要用到 AddressBook.frame ...

随机推荐

  1. Selenium2+python自动化25-js处理日历控件(修改readonly属性)

    前言 日历控件是web网站上经常会遇到的一个场景,有些输入框是可以直接输入日期的,有些不能,以我们经常抢票的12306网站为例,详细讲解如何解决日历控件为readonly属性的问题. 基本思路:先用j ...

  2. CMS为什么采用“标记-清除”算法

    分代式GC里,年老代常用mark-sweep:或者是mark-sweep/mark-compact的混合方式,一般情况下用mark-sweep,统计估算碎片量达到一定程度时用mark-compact. ...

  3. win10下vs2015配置Opencv3.1.0过程详解

    下载安装Opencv3.1.0 下载Opencv3.1.0,进入官网,点击opencv for windows即可下载.  点击运行下载好的文件.实际上,opencv的安装程序就是解压缩文件,个人因为 ...

  4. java项目@override报错问题

    有时候Java的Eclipse工程换一台电脑后编译总是@override报错,把@override去掉就好了,但不能从根本上解决问题,因为有时候有@override的地方超级多. 这是jdk的问题,@ ...

  5. js常用功能汇总

    var Utils = function() { this.Tools; this.ui; }; Utils = new Utils(); Utils.prototype.Tools = { year ...

  6. who is the middle

    Description FJ is surveying his herd to find the most average cow. He wants to know how much milk th ...

  7. java有符号无符号的转换

    数据处理中常常遇到基本数据类型的操作,java都是有符号的数据,而与下位机通信中常常遇到无符号的比如uint8, uint16,uint32等等 1.为了完成这个功能还专门采用ByteBuffer的方 ...

  8. jsp 和jspf

    http://www.cnblogs.com/liaojie970/p/5035077.html

  9. Java学习笔记 第一章 入门<转>

    第一章 JAVA入门 一.基础常识 1.软件开发 什么是软件? 软件:一系列按照特定顺序组织的计算机数据和指令的集合 系统软件:DOS,Windows,Linux 应用软件:扫雷.QQ.迅雷 什么是开 ...

  10. nginx 从vagant挂载目录中加载nginx.conf配置进行开机启动

    nginx从vagrant挂载目录中读取配置启动,将nginx加入开机启动项!开机启动的时候nginx会因为加载不了配置导致启动失败! 原因是开机启动nginx服务在vagrant挂载之前,导致无法正 ...