码迷,mamicode.com
首页 > 移动开发 > 详细

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

时间:2015-06-24 22:20:18      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:

调用地图功能的实现

一:苹果自带地图

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

  第一步:导入地图文件  #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开发——高级技术&调用地图功能的实现

标签:

原文地址:http://www.cnblogs.com/iCocos/p/4598648.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!