地圖
準備工作
- 匯入MapKit框架(iOS5之後不在需要程式設計師自己匯入)
- 匯入主標頭檔案**#import <MapKit/MapKit.h>**
- MapKit框架中所有的資料型別的字首都是MK。
- MapKit有一個比較重要的UI控制元件:MKMapView,專門用於地圖的顯示
- 設定MKMapView的userTrackingModes屬性可以跟蹤顯示使用者的當前位置
typedef NS_ENUM(NSInteger, MKUserTrackingMode) {
MKUserTrackingModeNone = 0, // 不跟蹤使用者的位置
MKUserTrackingModeFollow, //跟蹤並在地圖上顯示使用者當前的位置
MKUserTrackingModeFollowWithHeading, //跟蹤並在地圖上顯示使用者當前的位置,地圖會隨著使用者前進的方向進行旋轉。
} NS_ENUM_AVAILABLE(NA, 5_0) __WATCHOS_PROHIBITED;
複製程式碼
- 可以通過設定MKMapView的mapType設定地圖的型別(mapType是一個列舉值)
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),顯示道路和附加元素的Flyover
}
複製程式碼
建立一個地圖
- 在延展裡宣告一個地圖的屬性
@interface RootViewController ()<MKMapViewDelegate>
@property (strong, nonatomic)MKMapView *mapView;
@property (assign, nonatomic)CGRect frame;
@end
複製程式碼
- 把這個屬性寫成懶載入並將它新增檢視控制器的view上
-(MKMapView *)mapView{
if (!_mapView) {
_mapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_mapView];
}return _mapView;
}
複製程式碼
- 為了讓地圖適配螢幕的旋轉,我們需要重寫下面這個方法 這個方法的返回值是一個列舉型別,返回的是支援螢幕旋轉的方向
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
UIInterfaceOrientationMaskPortrait//home鍵在下
UIInterfaceOrientationMaskLandscapeLeft//支援向左旋轉
UIInterfaceOrientationMaskLandscapeRight//支援向右旋轉
UIInterfaceOrientationMaskPortraitUpsideDown//支援上下
UIInterfaceOrientationMaskLandscape//支援左右同時旋轉
UIInterfaceOrientationMaskAll//支援四個方向
UIInterfaceOrientationMaskAllButUpsideDown//支援上左右
}
複製程式碼
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;//讓旋轉支援所有方向
}
複製程式碼
使用下面的這個方法,可以監測到螢幕的旋轉,在這個我們徐亞我改變地圖的位置資訊。 在此之前我們需要現在viewDidLoad中獲取到程式啟動時的位置資訊
-(void)viewDidLoad{
self.frame = self.view.frame;
}
複製程式碼
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:
(id<UIViewControllerTransitionCoordinator>)coordinator{
CGRect temp = CGRectMake(0, 0, 0, 0);
if (size.width > size.height) {
temp = CGRectMake(0, 0, self.frame.size.height, self.frame.size.width);
}else{
temp = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
}
self.mapView.frame = temp;
}
複製程式碼
- 設定地圖的跟蹤屬性,以及使用的地圖型別
//使用者位置追蹤(使用者位置追蹤用於標記使用者當前位置,此時會呼叫定位服務)
self.mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
self.mapView.mapType = MKMapTypeStandard;//普通地圖
self.mapView.delegate = self;//指定代理人,下面我們需要實現一些地圖和大頭針的下一方法。
複製程式碼
完成以上的四步,我們就可以在我們的模擬器上看到地圖了 下面我們需要在地圖上設定它的另外一個屬性,大頭針。
地圖的代理方法
- 當地圖顯示的位置發生改變,就會執行此代理方法。
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
//將得到的location資訊 反地理編碼成位置名稱。
NSLog(@"位置發生變化了");
CLGeocoder *geocoder = [[CLGeocoder alloc]init];
[geocoder reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
CLPlacemark *newPlacemark = placemarks.lastObject;
//設定大頭針的標題
userLocation.title = newPlacemark.country;
userLocation.subtitle = newPlacemark.name;
}];
}
複製程式碼
- 地圖上顯示的區域即將發生改變的時候呼叫的方法
-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated{
NSLog(@"地圖上顯示的區域即將發生改變");
}
複製程式碼
- 地圖上的位置顯示的區域已經發生改變的時候呼叫的方法。
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
NSLog(@"地圖上的位置顯示的區域已經發生改變");
}
複製程式碼
大頭針
在iOS開發中經常會標記某個位置,需要使用地圖示註,也就是大家俗稱的“大頭針”。在這裡系統為我們提供了一個大頭針的類MKPointAnnotation
系統的大頭針
MKPointAnnotation *pointAnnotation = [[MKPointAnnotation alloc]init];
pointAnnotation.coordinate = CLLocationCoordinate2DMake(35, 108);//設定大頭針的位置資訊
/**
* 設定大頭針的標題
*/
pointAnnotation.title = @"甘家寨";//主標題
pointAnnotation.subtitle = @"大牛夜市";//副標題
[self.mapView addAnnotation:pointAnnotation];//將大頭針新增到地圖上
複製程式碼
自定義大頭針
只要一個NSObject類實現MKAnnotation協議就可以作為一個大頭針,通常會重寫協議中coordinate(標記位置)、title(標題)、subtitle(子標題)三個屬性,然後在程式中建立大頭針物件並呼叫**addAnnotation:**方法新增大頭針即可(之所以iOS沒有定義一個基類實現這個協議供開發者使用,多數原因應該是MKAnnotation是一個模型物件,對於多數應用模型會稍有不同,例如後面的內容中會給大頭針模型物件新增其他屬性)。
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface MyAnnotation : NSObject<MKAnnotation>//遵循annotation協議
@property (assign, nonatomic)CLLocationCoordinate2D coordinate;//位置資訊
@property (copy, nonatomic)NSString *title;//標題
@property (copy, nonatomic)NSString *subtitle;//副標題
@end
複製程式碼
使用自定義的大頭針
- (void)myannotation{
MyAnnotation *annotation = [[MyAnnotation alloc]init];
annotation.coordinate = CLLocationCoordinate2DMake(35, 107);
annotation.title = @"大雁塔";
annotation.subtitle = @"西安市";
[self.mapView addAnnotation:annotation];
}
複製程式碼
自定義大頭針的協議方法
每插入一個大頭針,都會執行一次代理方法。 這個方法有點類似於tableView的重用機制,能有效的節約資源。
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:
(id<MKAnnotation>)annotation{
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"insert"];
if (!annotationView) {
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"insert"];
}
if ([annotation isKindOfClass:[MyAnnotation class]]) {
annotationView.pinTintColor = [UIColor blackColor];//設定大頭針的顏色
annotationView.animatesDrop = YES;//設定從天而降的效果
annotationView.canShowCallout = YES;//在點選大頭針時是否顯示標題
annotationView.leftCalloutAccessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"2.jpeg"]];//設定大頭針的左側輔助檢視
return annotationView;
}else{
return nil;//當前方法返回值為nil的時候大頭針保持系統的樣子
}
}
複製程式碼