標籤:
1、概述
MapKit架構使用前提:
匯入架構:
匯入主標頭檔:
#import <MapKit/MapKit.h>
MapKit架構使用須知:
MapKit架構中所有資料類型的首碼都是MK。
MapKit有一個比較重要的UI控制項 :MKMapView,專門用於地圖顯示。
2、跟蹤顯示使用者的位置
設定MKMapView的userTrackingMode屬性可以跟蹤顯示使用者的當前位置:
MKUserTrackingModeNone :不跟蹤使用者的位置
MKUserTrackingModeFollow :跟蹤並在地圖上顯示使用者的當前位置
MKUserTrackingModeFollowWithHeading :跟蹤並在地圖上顯示使用者的當前位置,地圖會跟隨使用者的前進方向進行旋轉
是跟蹤效果:
藍色發光圓點就是使用者的當前位置。
藍色發光原點,專業術語叫做“圖釘”。
3、地圖的類型
可以通過設定MKMapView的mapViewType設定地圖類型:
MKMapTypeStandard :普通地圖(左圖)
MKMapTypeSatellite :衛星雲圖 (中圖)
MKMapTypeHybrid :普通地圖覆蓋於衛星雲圖之上(右圖)
4、MKMapView的代理
MKMapView可以設定一個代理對象,用來監聽地圖的相關行為。
常見的代理方法有:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:
(MKUserLocation *)userLocation;
調用非常頻繁,不斷監測使用者的當前位置
每次調用,都會把使用者的最新位置(userLocation參數)傳進來
-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:
(BOOL)animated;
地圖的顯示地區即將發生改變的時候調用
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:
(BOOL)animated;
地圖的顯示地區已經發生改變的時候調用
5、MKUserLocation
MKUserLocation其實是個圖釘模型,包括以下屬性。
@property (nonatomic, copy) NSString *title;
顯示在圖釘上的標題
@property (nonatomic, copy) NSString *subtitle;
顯示在圖釘上的子標題
@property (readonly, nonatomic) CLLocation *location;
地理位置資訊
6、設定地圖的顯示
通過MKMapView的下列方法,可以設定地圖顯示的位置和地區。
設定地圖的中心點位置:
@property (nonatomic) CLLocationCoordinate2D centerCoordinate;
-(void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated;
設定地圖的顯示地區:
@property (nonatomic) MKCoordinateRegion region;
-(void)setRegion:(MKCoordinateRegion)region animated:
(BOOL)animated;
例如:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:
(MKUserLocation *)userLocation
{
userLocation.title = @"天朝帝都";
userLocation.subtitle = @"是個非常牛逼的地方!";
CLLocationCoordinate2D center = userLocation.location.coordinate;
// 設定地圖的顯示範圍
MKCoordinateSpan span = MKCoordinateSpanMake(0.021321, 0.019366);//數值越小地圖放的越大(地理位置越詳細),位置越精確
MKCoordinateRegion region = MKCoordinateRegionMake(center, span);//設定地圖中心點為當前定位到的位置
[mapView setRegion:region animated:YES];
}
7、MKCoordinateRegion結構體
MKCoordinateRegion是一個用來表示地區的結構體,定義如下:
typedef struct {
CLLocationCoordinate2D center; // 地區的中心點位置
MKCoordinateSpan span; // 地區的跨度
} MKCoordinateRegion;
MKCoordinateSpan的定義:
typedef struct {
CLLocationDegrees latitudeDelta; // 緯度跨度
CLLocationDegrees longitudeDelta; // 經度跨度
} MKCoordinateSpan;
8、圖釘的基本操作
添加一個圖釘
- (void)addAnnotation:(id <MKAnnotation>)annotation;
添加多個圖釘
- (void)addAnnotations:(NSArray *)annotations;
移除一個圖釘
- (void)removeAnnotation:(id <MKAnnotation>)annotation;
移除多個圖釘
- (void)removeAnnotations:(NSArray *)annotations;
(id <MKAnnotation>)annotation參數是什麼東西?
圖釘模型對象:用來封裝圖釘的資料,比如圖釘的位置、標題、子標題等資料
9、圖釘模型
建立一個圖釘模型類
#import <MapKit/MapKit.h>
@interface MJTuangouAnnotation : NSObject <MKAnnotation>
/** 座標位置 */
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
/** 標題 */
@property (nonatomic, copy) NSString *title;
/** 子標題 */
@property (nonatomic, copy) NSString *subtitle;
@end
10、添加圖釘
MJTuangouAnnotation *anno = [[MJTuangouAnnotation alloc] init];
anno.title = @"這是位置";
anno.subtitle = @“這是位置描述";
anno.coordinate = CLLocationCoordinate2DMake(40, 116);
[self.mapView addAnnotation:anno];
例如,點擊螢幕MKMapView哪裡,就在哪裡添加一個圖釘:
首先,要遵守代理協議:MKMapViewDelegate
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.跟蹤使用者位置(顯示使用者的具體位置)
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
// 2.設定代理
self.mapView.delegate = self;
// 3.監聽mapView的點擊事件
[self.mapView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapMapView:)]];
}
/**
* 監聽mapView的點擊
*/
- (void)tapMapView:(UITapGestureRecognizer *)tap
{
// 1.獲得使用者在mapView點擊的位置(x,y)
CGPoint point = [tap locationInView:tap.view];
// 2.將數學座標 轉為 地理經緯度座標
CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
// 3.建立圖釘模型,添加圖釘到地圖上
MJAnnotation *anno = [[MJAnnotation alloc] init];
anno.coordinate = coordinate;//設定圖釘的經緯座標
anno.title = @"這是位置";
anno.subtitle = @"這是位置描述";
[self.mapView addAnnotation:anno];//添加圖釘
}
由於系統內建的圖釘MKAnnotation的屬性都是唯讀,不能改變其屬性,也就是說不能設定其位置、title等,解決辦法為自訂MKAnnotation,重寫其屬性,將它的需要用到的屬性改為可寫的。方法為建立普通類MJAnnotation,使它遵守MKAnnotation協議,匯入架構標頭檔<MapKit/MapKit.h>,然後在MJAnnotation.h檔案中重寫屬性,不用動MJAnnotation.m檔案。如下:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface MJAnnotation : NSObject <MKAnnotation>
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
//原來為@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
//原來為@property (nonatomic, readonly, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
//原來為@property (nonatomic,readonly copy) NSString *subtitle;
@end
11、自訂圖釘
很多情況下,需要自訂圖釘的顯示樣式,比如顯示一張圖片:
自訂圖釘步驟:
第一步:自訂圖釘(MKAnnotation)
MJTuangouAnnotation.h檔案如下(不需要動.m檔案):
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface MJTuangouAnnotation : NSObject <MKAnnotation>
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
@property (nonatomic, copy) NSString *icon;//這條屬性不是系統內建的,是我們手動添加的
@end
第二步:使控制器遵守MKMapViewDelegate協議,並將控制器設定為MKMapView的代理
self.mapView.delegate = self;
第三步:實現下面的代理方法,返回圖釘控制項
- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id <MKAnnotation>)annotation;
例如:
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.美食
MJTuangouAnnotation *anno0 = [[MJTuangouAnnotation alloc] init];
anno0.title = @"xxx大飯店";
anno0.subtitle = @"全場一律15折,會員20折";
anno0.coordinate = CLLocationCoordinate2DMake(39, 115);
anno0.icon = @"eat";
[self.mapView addAnnotation:anno0];
// 2.電影
MJTuangouAnnotation *anno1 = [[MJTuangouAnnotation alloc] init];
anno1.title = @"xxx影院";
anno1.subtitle = @"最新大片:美國隊長2,即將上映。。。";
anno1.coordinate = CLLocationCoordinate2DMake(29, 110);
anno1.icon = @"movie";
[self.mapView addAnnotation:anno1];
self.mapView.delegate = self;//設定代理
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if (![annotation isKindOfClass:[MJTuangouAnnotation class]]) return nil;//使自訂的圖釘能和系統預設圖釘共存,如果不加此行代碼,定位的時候會出現系統icon屬性沒有找到的屬性,因為該屬性不是系統包含的,是我們手動添加的。
static NSString *ID = @"tuangou";
// 從緩衝池中取出可以迴圈利用的圖釘view
MKAnnotationView *annoView =
[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
if (annoView == nil) {
annoView=[[MKAnnotationView alloc] initWithAnnotation:
annotation reuseIdentifier:ID];
// 設定是否顯示標題和子標題
annoView.canShowCallout = YES;
// 設定圖釘描述的位移量
annoView.calloutOffset = CGPointMake(0, -10);
// 設定圖釘描述右邊的控制項
annoView.rightCalloutAccessoryView =
[UIButton buttonWithType:UIButtonTypeContactAdd];
// 設定圖釘描述左邊的控制項
annoView.leftCalloutAccessoryView =
[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
// 傳遞模型
annoView.annotation = annotation;
// 設定圖片,要手動設定圖片而不用手動設定標題是因為標題是內建屬性,而icon是我們添加的屬性。
MJTuangouAnnotation *tuangouAnno = annotation;
annoView.image = [UIImage imageNamed:tuangouAnno.icon];
return annoView;//返回nil則顯示預設圖釘
}
第四步:根據傳進來的(id <MKAnnotation>)annotation參數建立並返回對應的圖釘控制項。
【備忘】代理方法的使用注意:
如果返回nil,顯示出來的圖釘就採取系統的預設樣式。
標識使用者位置的藍色發光圓點,它也是一個圖釘,當顯示這個圖釘時,也會調用代理方法。
因此,需要在代理方法中分清楚(id <MKAnnotation>)annotation參數代表自訂的圖釘還是藍色發光圓點。
12、MKAnnotationView
地圖上的圖釘控制項是MKAnnotationView。
MKAnnotationView的屬性:
@property (nonatomic, strong) id <MKAnnotation> annotation;
圖釘模型
@property (nonatomic, strong) UIImage *image;
顯示的圖片
@property (nonatomic) BOOL canShowCallout;
是否顯示標註
@property (nonatomic) CGPoint calloutOffset;
標註的位移量
@property (strong, nonatomic) UIView *rightCalloutAccessoryView;
標註右邊顯示什麼控制項
@property (strong, nonatomic) UIView *leftCalloutAccessoryView;
標註左邊顯示什麼控制項
11、 MKPinAnnotationView
MKPinAnnotationView是MKAnnotationView的子類。
MKPinAnnotationView比MKAnnotationView多了2個屬性:
@property (nonatomic) MKPinAnnotationColor pinColor;
圖釘顏色
@property (nonatomic) BOOL animatesDrop;
圖釘第一次顯示時是否從天而降
iOS開發之MapKit