iOS原生地圖開發詳解git
在上一篇博客中:http://my.oschina.net/u/2340880/blog/414760。對iOS中的定位服務進行了詳細的介紹與參數說明,在開發中,地位服務每每與地圖框架結合使用,這篇博客主要對iOS官方的地圖框架MapKit.framework進行介紹。數組
地圖視圖的展現依賴於MKMapView這個類,這個類繼承於UIView,所以和其餘View的使用方法相似。在咱們須要展示地圖的地方:app
- (void)viewDidLoad { [super viewDidLoad]; MKMapView * mapView =[[MKMapView alloc]initWithFrame:self.view.frame]; [self.view addSubview:mapView]; }
運行發現,一張世界地圖就在咱們的設備上了,apple內置的地圖數據是由高德提供的。框架
能夠經過MKMapView的mapType這個屬性設置地圖的模式:ide
@property (nonatomic) MKMapType mapType;動畫
枚舉以下:ui
typedef NS_ENUM(NSUInteger, MKMapType) { MKMapTypeStandard = 0,//標準式的行政地圖(會顯示城市,街道等) MKMapTypeSatellite,//標準的衛星地圖 MKMapTypeHybrid//混合地圖(在衛星圖上顯示街道等名稱) };
在百度地圖等第三方地圖服務的SDK中,都會提供一個相似zoomLevel比例尺的屬性。經過官方的API設置這個屬性有些麻煩,可是也更加靈活。首先,設置地圖的中心位置和比例尺是經過region這個屬性實現的。region結構體以下:atom
typedef struct { CLLocationCoordinate2D center;//地圖中心的經緯度 MKCoordinateSpan span;//地圖顯示的經緯度範圍 } MKCoordinateRegion;
這個結構體中包含了兩個結構體,其中CLLocationCoordinate2D很好理解,就是簡單的經緯度,解釋以下:spa
typedef struct { CLLocationDegrees latitude;//緯度,北緯爲正,南緯爲負 CLLocationDegrees longitude;//經度,東經爲正,西經爲負 } CLLocationCoordinate2D;
MKCoordinateSpan這個結構體比較複雜,以下:.net
typedef struct { CLLocationDegrees latitudeDelta;//緯度範圍 CLLocationDegrees longitudeDelta;//經度範圍 } MKCoordinateSpan;
這個結構體定義的應該是一個範圍,由於北緯南緯加起來180°,因此緯度範圍的取值應爲0-180。同理,經度範圍的取值範圍爲0-360。
經過上面的介紹,咱們舉個例子,將北京市設爲地圖的中心區域,而且比例設置爲顯示北京大小。經過百度,首先知道北京市界的地理座標爲:北緯39」26’至41」03’,東經115」25’至 117」30’。北京市區座標爲:北緯39.9」,東經116. 3」。代碼以下:
mapView.region=MKCoordinateRegionMake(CLLocationCoordinate2DMake(39.26, 116.3), MKCoordinateSpanMake(1.8, 2.05));
運行後能夠看到,北京市基本上是在地圖中心的,效果以下:
注意:MKCoordinateSpan的顯示範圍是取決於大的一邊的,好比若是咱們這樣寫:
MKCoordinateSpanMake(1.8, 360);
最後依然會顯示整個世界地圖。
- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated;
這個方法能夠在設置後給地圖加上動畫效果
@property (nonatomic) CLLocationCoordinate2D centerCoordinate;
設置地圖的中心點位置
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated;
設置地圖的中心點位置,並附帶動畫效果
- (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(UIView *)view;
將經緯度轉換爲視圖上的座標
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view;
將視圖上的座標轉換爲經緯度
- (CGRect)convertRegion:(MKCoordinateRegion)region toRectToView:(UIView *)view;
將地理顯示的區域轉換爲視圖上的座標區域
- (MKCoordinateRegion)convertRect:(CGRect)rect toRegionFromView:(UIView *)view;
將視圖上的座標區域轉換爲地理區域
@property (nonatomic, getter=isZoomEnabled) BOOL zoomEnabled;
設置是否容許捏合手勢進行地圖縮放
@property (nonatomic, getter=isScrollEnabled) BOOL scrollEnabled;
設置是否容許滑動
@property (nonatomic, getter=isRotateEnabled) BOOL rotateEnabled;
設置是否容許旋轉地圖
@property (nonatomic, getter=isPitchEnabled) BOOL pitchEnabled;
設置是否支持3D效果
@property (nonatomic) BOOL showsPointsOfInterest;
設置是否顯示興趣點,例如學校,醫院等
@property (nonatomic) BOOL showsBuildings;
設置是否顯示建築物輪廓,只在標準的地圖中有效
@property (nonatomic) BOOL showsUserLocation;
是否顯示用戶位置
@property (nonatomic) MKUserTrackingMode userTrackingMode;
- (void)setUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated;
設置更新用戶位置的模式,當顯示用戶位置設置爲YES,這個方法也設置了後,地圖框架爲咱們直接集成了定位,地圖上就會顯示咱們的位置,模式的枚舉以下:
typedef NS_ENUM(NSInteger, MKUserTrackingMode) { MKUserTrackingModeNone = 0, // 不跟蹤用戶位置 MKUserTrackingModeFollow, // 跟蹤用戶位置 MKUserTrackingModeFollowWithHeading, // 當方向改變時跟蹤用戶位置 }
@property (nonatomic, readonly) MKUserLocation *userLocation;
獲取用戶位置的標註
@property (nonatomic, readonly, getter=isUserLocationVisible) BOOL userLocationVisible;
獲取用戶位置是否可見
- (void)addAnnotation:(id <MKAnnotation>)annotation;
在地圖上添加一個標註
- (void)addAnnotations:(NSArray *)annotations;
在地圖上添加一組標註
- (void)removeAnnotation:(id <MKAnnotation>)annotation;
移除一個標註
- (void)removeAnnotations:(NSArray *)annotations;
移除一組標註
@property (nonatomic, readonly) NSArray *annotations;
獲取全部標註數組
- (MKAnnotationView *)viewForAnnotation:(id <MKAnnotation>)annotation;
獲取標註的視圖
- (MKAnnotationView *)dequeueReusableAnnotationViewWithIdentifier:(NSString *)identifier;
獲取複用的標註
- (void)selectAnnotation:(id <MKAnnotation>)annotation animated:(BOOL)animated;
選中一個標註
- (void)deselectAnnotation:(id <MKAnnotation>)annotation animated:(BOOL)animated;
取消選中一個標註
@property (nonatomic, copy) NSArray *selectedAnnotations;
選中標註的數組
- (void)addOverlay:(id <MKOverlay>)overlay level:(MKOverlayLevel)level;
添加一個地圖覆蓋物,level是設置一個層級,枚舉以下:
typedef NS_ENUM(NSInteger, MKOverlayLevel) { MKOverlayLevelAboveRoads = 0, // 覆蓋物位於道路之上 MKOverlayLevelAboveLabels//覆蓋物位於標籤之上 }
- (void)addOverlays:(NSArray *)overlays level:(MKOverlayLevel)level;
添加一組地圖覆蓋物
- (void)removeOverlay:(id <MKOverlay>)overlay;
移除一個地圖覆蓋物
- (void)removeOverlays:(NSArray *)overlays;
移除一組地圖覆蓋物
- (void)insertOverlay:(id <MKOverlay>)overlay atIndex:(NSUInteger)index level:(MKOverlayLevel)level;
在索引處插入一個地圖覆蓋物
- (void)insertOverlay:(id <MKOverlay>)overlay aboveOverlay:(id <MKOverlay>)sibling;
將一個地圖覆蓋物插在到某個覆蓋物之上
- (void)insertOverlay:(id <MKOverlay>)overlay belowOverlay:(id <MKOverlay>)sibling;
將一個地圖覆蓋物插入到某個覆蓋物之下
- (void)exchangeOverlay:(id <MKOverlay>)overlay1 withOverlay:(id <MKOverlay>)overlay2;
替換一個地圖覆蓋物
@property (nonatomic, readonly) NSArray *overlays;
地圖覆蓋物數組
- (NSArray *)overlaysInLevel:(MKOverlayLevel)level;
層級屬性下的東土覆蓋物數組
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
地圖顯示位置將要改變時調用的方法
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
地圖顯示位置已經改變時調用的方法
- (void)mapViewWillStartLoadingMap:(MKMapView *)mapView;
地圖將要加載時調用的方法
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView;
地圖加載完成時執行的方法
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error;
地圖加載失敗時執行的方法
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
渲染標註視圖時調用的方法,能夠經過這個方法自定義標註視圖
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
標註添加完成後調用的方法
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view;
選中標註時調用的方法
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view;
取消選中標註時調用的方法
- (void)mapViewWillStartLocatingUser:(MKMapView *)mapView;
將要開始定位用戶位置時調用的方法
- (void)mapViewDidStopLocatingUser:(MKMapView *)mapView;
中止定位用戶位置時調用的方法
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation;
更新用戶位置時調用的方法
- (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error;
更新用戶位置失敗時調用的方法
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
fromOldState:(MKAnnotationViewDragState)oldState;
標註拖動狀態改變調用的方法,MKAnnotationViewDragState的枚舉以下:
typedef NS_ENUM(NSUInteger, MKAnnotationViewDragState) { MKAnnotationViewDragStateNone = 0, // 初始狀態 MKAnnotationViewDragStateStarting, // 開始拖動時 MKAnnotationViewDragStateDragging, // 正在拖動 MKAnnotationViewDragStateCanceling, // 取消拖動 MKAnnotationViewDragStateEnding // 結束拖動 };
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated;
定位用戶位置模式改變時調用的方法
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay;
渲染覆蓋物視圖時調用的方法,能夠自定義覆蓋物視圖
- (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews;
添加完成覆蓋物數組執行的方法
備註:在iOS9中,地圖類型的枚舉又添加了兩種:
typedef NS_ENUM(NSUInteger, MKMapType) { MKMapTypeStandard = 0,//標準 MKMapTypeSatellite,//衛星 MKMapTypeHybrid,//混合 MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0),//立體衛星 MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0),//立體混合 } NS_ENUM_AVAILABLE(10_9, 3_0) __WATCHOS_PROHIBITED;
注:因篇幅限制,關於系統大頭針和自定義標註的應用、地圖覆蓋物的應用將在下一篇博客中討論。
疏漏之處 歡迎指正
專一技術,熱愛生活,交流技術,也作朋友。
——琿少 QQ羣:203317592