調用地圖功能的實現ios
一:蘋果自帶地圖git
學習如逆水行舟,不進則退。古人告訴咱們要不斷的反思和總結,日思則日精,月思則月精,年思則年精。只有不斷的嘗試和總結,才能讓咱們的工做和生活更加 輕鬆愉快和美好。連着作了兩個大的商城外包項目,智慧城市,搜牧通,花費了近四個月的時間,終於在反覆修改後完美收工。期間的困難自沒必要說,之後多多總結 和溝通吧。百度地圖的使用以前已經發表了一篇文章,說的很詳細了,這裏再也不涉及,言歸正傳,咱們說一下如何調用蘋果自帶的地圖程序員
第一步:導入地圖文件 #import <MapKit/MapKit.h>數據庫
第二步:獲取當前位置和目的地的經緯度,而後打開地圖便可api
//獲取當前位置數組
1 MKMapItem *mylocation = [MKMapItem mapItemForCurrentLocation]; app
//當前經維度框架
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兒童手環。因此這裏簡單介紹定位與地圖。
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 }
地圖我目前用過系統、百度以及高德,開發人員使用都是差很少的,下面的代碼涉及的類都是高德地圖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