MapKit框架的基本使用
用于地圖展示,例如大頭針,路線(xiàn)、覆蓋層展示等(著重界面展示)
導(dǎo)入主頭文件 #import <MapKit/MapKit.h>
MapKit有一個(gè)比較重要的UI控件:MKMapView,專(zhuān)門(mén)用于地圖顯示



MKMapTypeSatellite.png

MKMapTypeHybridFlyover.png

MKMapTypeHybrid.png
@interface ViewController ()
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
/** 位置管理者 */
@property (nonatomic, strong) CLLocationManager *locationM;
@end
@implementation ViewController
#pragma mark -懶加載
-(CLLocationManager *)locationM
{
if (!_locationM) {
_locationM = [[CLLocationManager alloc] init];
// 版本適配
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
[_locationM requestAlwaysAuthorization];
}
}
return _locationM;
}
- (void)viewDidLoad {
[super viewDidLoad];
// MKMapTypeStandard = 0, // 標(biāo)準(zhǔn)地圖
// MKMapTypeSatellite, // 衛(wèi)星云圖
// MKMapTypeHybrid, // 混合(在衛(wèi)星云圖上加了標(biāo)準(zhǔn)地圖的覆蓋層)
// MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0), // 3D立體
// MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0), // 3D混合
// 設(shè)置地圖顯示樣式(必須注意,設(shè)置時(shí) 注意對(duì)應(yīng)的版本)
self.mapView.mapType = MKMapTypeStandard;
// 設(shè)置地圖的控制項(xiàng)
// 是否可以滾動(dòng)
// self.mapView.scrollEnabled = NO;
// 縮放
// self.mapView.zoomEnabled = NO;
// 旋轉(zhuǎn)
// self.mapView.rotateEnabled = NO;
// 設(shè)置地圖的顯示項(xiàng)(注意::版本適配)
// 顯示建筑物
self.mapView.showsBuildings = YES;
// 指南針
self.mapView.showsCompass = YES;
// 興趣點(diǎn)
self.mapView.showsPointsOfInterest = YES;
// 比例尺
self.mapView.showsScale = YES;
// 交通
self.mapView.showsTraffic = YES;
// 顯示用戶(hù)位置
[self locationM];
// 顯示用戶(hù)位置, 但是地圖并不會(huì)自動(dòng)放大到合適比例
// self.mapView.showsUserLocation = YES;
/**
* MKUserTrackingModeNone = 0, 不追蹤
MKUserTrackingModeFollow, 追蹤
MKUserTrackingModeFollowWithHeading, 帶方向的追蹤
*/
// 不但顯示用戶(hù)位置, 而且還會(huì)自動(dòng)放大地圖到合適的比例(也要進(jìn)行定位授權(quán))
// 不靈光
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
}
@end
MapKit框架的中級(jí)使用--區(qū)域顯示
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
/** 位置管理者 */
@property (nonatomic, strong) CLLocationManager *locationM;
@end
@implementation ViewController
#pragma mark -懶加載
-(CLLocationManager *)locationM
{
if (!_locationM) {
_locationM = [[CLLocationManager alloc] init];
// 版本適配
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
[_locationM requestAlwaysAuthorization];
}
}
return _locationM;
}
- (void)viewDidLoad {
[super viewDidLoad];
// MKMapTypeStandard = 0, // 標(biāo)準(zhǔn)地圖
// MKMapTypeSatellite, // 衛(wèi)星云圖
// MKMapTypeHybrid, // 混合(在衛(wèi)星云圖上加了標(biāo)準(zhǔn)地圖的覆蓋層)
// MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0), // 3D立體
// MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0), // 3D混合
// 設(shè)置地圖顯示樣式(必須注意,設(shè)置時(shí) 注意對(duì)應(yīng)的版本)
self.mapView.mapType = MKMapTypeStandard;
// 設(shè)置地圖的控制項(xiàng)
// 是否可以滾動(dòng)
// self.mapView.scrollEnabled = NO;
// 縮放
// self.mapView.zoomEnabled = NO;
// 旋轉(zhuǎn)
// self.mapView.rotateEnabled = NO;
// 設(shè)置地圖的顯示項(xiàng)(注意::版本適配)
// 顯示建筑物
self.mapView.showsBuildings = YES;
// 指南針
self.mapView.showsCompass = YES;
// 興趣點(diǎn)
self.mapView.showsPointsOfInterest = YES;
// 比例尺
self.mapView.showsScale = YES;
// 交通
self.mapView.showsTraffic = YES;
// 顯示用戶(hù)位置
[self locationM];
// 顯示用戶(hù)位置, 但是地圖并不會(huì)自動(dòng)放大到合適比例
self.mapView.showsUserLocation = YES;
/**
* MKUserTrackingModeNone = 0, 不追蹤
MKUserTrackingModeFollow, 追蹤
MKUserTrackingModeFollowWithHeading, 帶方向的追蹤
*/
// 不但顯示用戶(hù)位置, 而且還會(huì)自動(dòng)放大地圖到合適的比例(也要進(jìn)行定位授權(quán))
// 不靈光
// self.mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
}
#pragma mark -MKMapViewDelegate
/**
* 當(dāng)?shù)貓D獲取到用戶(hù)位置時(shí)調(diào)用
*
* @param mapView 地圖
* @param userLocation 大頭針數(shù)據(jù)模型
*/
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
/**
* MKUserLocation : 專(zhuān)業(yè)術(shù)語(yǔ): 大頭針模型 其實(shí)喊什么都行, 只不過(guò)這個(gè)類(lèi)遵循了大頭針數(shù)據(jù)模型必須遵循的一個(gè)協(xié)議 MKAnnotation
// title : 標(biāo)注的標(biāo)題
// subtitle : 標(biāo)注的子標(biāo)題
*/
userLocation.title = @"小碼哥";
userLocation.subtitle = @"大神三期";
// 移動(dòng)地圖的中心,顯示用戶(hù)的當(dāng)前位置
// [mapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
// 顯示地圖的顯示區(qū)域
// 控制區(qū)域中心
CLLocationCoordinate2D center = userLocation.location.coordinate;
// 設(shè)置區(qū)域跨度
MKCoordinateSpan span = MKCoordinateSpanMake(0.077919, 0.044529);
// 創(chuàng)建一個(gè)區(qū)域
MKCoordinateRegion region = MKCoordinateRegionMake(center, span);
// 設(shè)置地圖顯示區(qū)域
[mapView setRegion:region animated:YES];
}
/**
* 地圖區(qū)域已經(jīng)改變時(shí)調(diào)用 --- 先縮放 獲取經(jīng)緯度跨度,根據(jù)經(jīng)緯度跨度顯示區(qū)域
*
* @param mapView 地圖
* @param animated 動(dòng)畫(huà)
*/
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
NSLog(@"%f---%f", mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta);
}
/**
* 地圖區(qū)域?qū)⒁淖儠r(shí)帶哦用
*
* @param mapView 地圖
* @param animated 動(dòng)畫(huà)
*/
-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
}
@end
MapKit框架的高級(jí)使用--大頭針
自定義大頭針( TGAnnotation)
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface TGAnnotation : NSObject<MKAnnotation>
// 控制大頭針扎在地圖上哪個(gè)位置
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
// 控制大頭針彈框顯示的標(biāo)題
@property (nonatomic, copy, nullable) NSString *title;
// 控制大頭針彈框顯示的子標(biāo)題
@property (nonatomic, copy, nullable) NSString *subtitle;
@end
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import "TGAnnotation.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
/** 地理編碼 */
@property (nonatomic, strong) CLGeocoder *geoC;
@end
@implementation ViewController
#pragma mark -懶加載
-(CLGeocoder *)geoC
{
if (!_geoC) {
_geoC = [[CLGeocoder alloc] init];
}
return _geoC;
}
/**
* 在地圖上操作大頭針, 就等于操作大頭針數(shù)據(jù)模型
* 添加大頭針: 添加大頭針數(shù)據(jù)模型
* 刪除大頭針: 刪除大頭針數(shù)據(jù)模型
*/
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 要求, 鼠標(biāo)點(diǎn)擊地圖的哪個(gè)位置, 就在對(duì)應(yīng)的位置加一個(gè)大頭針
// 1. 獲取當(dāng)前用戶(hù)在屏幕上點(diǎn)擊的點(diǎn)坐標(biāo)
UITouch *touch = [touches anyObject];
CGPoint center = [touch locationInView:self.mapView];
// 2. 把點(diǎn)坐標(biāo) 轉(zhuǎn)換成 在地圖對(duì)應(yīng)的地理坐標(biāo)
CLLocationCoordinate2D centerCoordinate = [self.mapView convertPoint:center toCoordinateFromView:self.mapView];
// 3. 設(shè)置彈框標(biāo)題和子標(biāo)題
NSString *title = @"連線(xiàn)";
NSString *subTitle = @"iOS技術(shù)部";
// 4. 調(diào)用自定義方法, 添加大頭針數(shù)據(jù)模型
TGAnnotation *annotation = [self addAnnotationWithCoordinate:centerCoordinate title:title andSubtitle:subTitle];
// 反地理編碼
CLLocation *location = [[CLLocation alloc] initWithLatitude:centerCoordinate.latitude longitude:centerCoordinate.longitude];
[self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 地標(biāo)對(duì)象
CLPlacemark *pl = [placemarks firstObject];
// 取詳細(xì)地址
NSString *name = pl.name;
// 獲取城市
NSString *city = pl.locality;
annotation.title = city;
annotation.subtitle = name;
}];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 獲取地圖上所有的大頭針數(shù)據(jù)模型
NSArray *annotations = self.mapView.annotations;
// 移除大頭針
[self.mapView removeAnnotations:annotations];
}
/**
* 自定義方法,添加大頭針
*
* @param center 大頭針扎在哪
* @param title 彈框標(biāo)題
* @param subTitle 彈框子標(biāo)題
*/
- (TGAnnotation *)addAnnotationWithCoordinate:(CLLocationCoordinate2D)center title:(NSString *)title andSubtitle:(NSString *)subTitle
{
TGAnnotation *annotation = [[TGAnnotation alloc] init];
annotation.coordinate = center;
annotation.title = title;
annotation.subtitle = subTitle;
[self.mapView addAnnotation:annotation];
return annotation;
}
- (void)addAnnotation
{
// 添加大頭針 == 添加大頭針數(shù)據(jù)模型
// 1. 創(chuàng)建大頭針數(shù)據(jù)模型
TGAnnotation *annotation = [[TGAnnotation alloc] init];
// 1.1 設(shè)置經(jīng)緯度
annotation.coordinate = self.mapView.centerCoordinate;
// 1.2 彈框標(biāo)題
annotation.title = @"連線(xiàn)";
// 1.3 彈框子標(biāo)題
annotation.subtitle = @"iOS研發(fā)部";
// 添加大頭針數(shù)據(jù)模型
[self.mapView addAnnotation:annotation];
}
#pragma mark -'MKMapViewDelegate
/**
* 地圖定位到之后調(diào)用
*
* @param mapView 地圖
* @param userLocation 大頭針數(shù)據(jù)模型
*/
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
}
@end
- 自定義大頭針
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import "XMGAnnotation.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
/** 位置管理者 */
@property (nonatomic, strong) CLLocationManager *locationM;
/** 地理編碼 */
@property (nonatomic, strong) CLGeocoder *geoC;
@end
@implementation ViewController
-(CLLocationManager *)locationM
{
if (!_locationM) {
_locationM = [[CLLocationManager alloc] init];
[_locationM requestAlwaysAuthorization];
}
return _locationM;
}
#pragma mark -懶加載
-(CLGeocoder *)geoC
{
if (!_geoC) {
_geoC = [[CLGeocoder alloc] init];
}
return _geoC;
}
/**
* 在地圖上操作大頭針, 就等于操作大頭針數(shù)據(jù)模型
* 添加大頭針: 添加大頭針數(shù)據(jù)模型
* 刪除大頭針: 刪除大頭針數(shù)據(jù)模型
*/
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 要求, 鼠標(biāo)點(diǎn)擊地圖的哪個(gè)位置, 就在對(duì)應(yīng)的位置加一個(gè)大頭針
// 1. 獲取當(dāng)前用戶(hù)在屏幕上點(diǎn)擊的點(diǎn)坐標(biāo)
// UITouch *touch = [touches anyObject];
// CGPoint center = [touch locationInView:self.mapView];
//
// // 2. 把點(diǎn)坐標(biāo) 轉(zhuǎn)換成 在地圖對(duì)應(yīng)的地理坐標(biāo)
// CLLocationCoordinate2D centerCoordinate = [self.mapView convertPoint:center toCoordinateFromView:self.mapView];
//
// // 3. 設(shè)置彈框標(biāo)題和子標(biāo)題
// NSString *title = @"小碼哥";
// NSString *subTitle = @"大神三期";
//
// // 4. 調(diào)用自定義方法, 添加大頭針數(shù)據(jù)模型
// XMGAnnotation *annotation = [self addAnnotationWithCoordinate:centerCoordinate title:title andSubtitle:subTitle];
//
// // 反地理編碼
// CLLocation *location = [[CLLocation alloc] initWithLatitude:centerCoordinate.latitude longitude:centerCoordinate.longitude];
// [self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// // 地標(biāo)對(duì)象
// CLPlacemark *pl = [placemarks firstObject];
//
// // 取詳細(xì)地址
// NSString *name = pl.name;
//
// // 獲取城市
// NSString *city = pl.locality;
//
// annotation.title = city;
// annotation.subtitle = name;
//
// }];
[self locationM];
// 在地圖上根據(jù)當(dāng)前用戶(hù)位置, 添加了一個(gè)大頭針視圖
self.mapView.showsUserLocation = YES;
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 獲取地圖上所有的大頭針數(shù)據(jù)模型
// NSArray *annotations = self.mapView.annotations;
// 移除大頭針
// [self.mapView removeAnnotations:annotations];
[self addAnnotation];
}
/**
* 自定義方法,添加大頭針
*
* @param center 大頭針扎在哪
* @param title 彈框標(biāo)題
* @param subTitle 彈框子標(biāo)題
*/
- (XMGAnnotation *)addAnnotationWithCoordinate:(CLLocationCoordinate2D)center title:(NSString *)title andSubtitle:(NSString *)subTitle
{
XMGAnnotation *annotation = [[XMGAnnotation alloc] init];
annotation.coordinate = center;
annotation.title = title;
annotation.subtitle = subTitle;
[self.mapView addAnnotation:annotation];
return annotation;
}
- (void)addAnnotation
{
// 添加大頭針 == 添加大頭針數(shù)據(jù)模型
// 1. 創(chuàng)建大頭針數(shù)據(jù)模型
XMGAnnotation *annotation = [[XMGAnnotation alloc] init];
// 1.1 設(shè)置經(jīng)緯度
annotation.coordinate = self.mapView.centerCoordinate;
// 1.2 彈框標(biāo)題
annotation.title = @"小碼哥";
// 1.3 彈框子標(biāo)題
annotation.subtitle = @"大神三期";
// 添加大頭針數(shù)據(jù)模型
[self.mapView addAnnotation:annotation];
}
/**
* 系統(tǒng)的大頭針視圖返回如果為nil , 實(shí)現(xiàn)方案
*
* @param mapView 地圖
* @param annotation 大頭針數(shù)據(jù)模型
*
* @return 大頭針視圖
*/
-(MKAnnotationView *)xitongmapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// -------模擬當(dāng)次方返回nil , 系統(tǒng)的實(shí)現(xiàn)方案
// 系統(tǒng)默認(rèn)的大頭這視圖 對(duì)應(yīng)的類(lèi) MKPinAnnotationView
// 大頭針標(biāo)識(shí)
static NSString *pinID = @"pinID";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pinID];
// 如果從緩存池取出的大頭針視圖為空, 就創(chuàng)建
if (pinView == nil) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinID];
}
// 重新設(shè)置數(shù)據(jù)模型 (一定要記得!!!), 為了防止循環(huán)利用時(shí), 數(shù)據(jù)混亂
pinView.annotation = annotation;
// 控制大頭針是否彈框
pinView.canShowCallout = YES;
// 設(shè)置大頭針顏色
// pinView.pinColor = MKPinAnnotationColorGreen;
pinView.pinTintColor = [UIColor blackColor]; // iOS9.0
// 設(shè)置大頭針下落動(dòng)畫(huà)
pinView.animatesDrop = YES;
// 設(shè)置大頭針顯示圖片(如果是系統(tǒng)的大頭針視圖, 那么就無(wú)法進(jìn)行自定義)
// pinView.image = [UIImage imageNamed:@"category_1.png"];
return pinView;
}
#pragma mark -MKMapViewDelegate
/**
* 地圖定位到之后調(diào)用
*
* @param mapView 地圖
* @param userLocation 大頭針數(shù)據(jù)模型
*/
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
}
/**
* 當(dāng)我們添加大頭針數(shù)據(jù)模型時(shí), 就會(huì)調(diào)用這個(gè)方法, 查找對(duì)應(yīng)的大頭針視圖
*
* @param mapView 地圖
* @param annotation 大頭針數(shù)據(jù)模型
*
* @return 大頭針視圖
* 注意: 如果這個(gè)方法, 沒(méi)有實(shí)現(xiàn), 或者, 這個(gè)方法返回nil, 那么系統(tǒng)就會(huì)調(diào)用系統(tǒng)默認(rèn)的大頭針視圖
*/
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// 如果是系統(tǒng)的大頭針數(shù)據(jù)模型, 那么使用系統(tǒng)默認(rèn)的大頭針視圖,
if([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
// 如果想要自定義大頭針視圖, 必須使用MKAnnotationView 或者 繼承 MKAnnotationView 的子類(lèi)
// 設(shè)置循環(huán)利用標(biāo)識(shí)
static NSString *pinID = @"pinID";
// 從緩存池取出大頭針數(shù)據(jù)視圖
MKAnnotationView *customView = [mapView dequeueReusableAnnotationViewWithIdentifier:pinID];
// 如果取出的為nil , 那么就手動(dòng)創(chuàng)建大頭針視圖
if (customView == nil) {
customView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinID];
}
// 1. 設(shè)置大頭針圖片
customView.image = [UIImage imageNamed:@"category_5.png"];
// 2. 設(shè)置彈框
customView.canShowCallout = YES;
// 2.1 設(shè)置大頭針偏移量
// customView.centerOffset = CGPointMake(100, -100);
// 2.2 設(shè)置彈框的偏移量
// customView.calloutOffset = CGPointMake(100, 100);
// 3. 自定義彈框
// 3.1 設(shè)置彈框左側(cè)的視圖
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
imageView.image = [UIImage imageNamed:@"htl.jpeg"];
customView.leftCalloutAccessoryView = imageView;
// 3.2 設(shè)置彈框右側(cè)視圖
UIImageView *imageView2 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
imageView2.image = [UIImage imageNamed:@"eason.jpg"];
customView.rightCalloutAccessoryView = imageView2;
// 3.3 設(shè)置彈框的詳情視圖(一定要注意,對(duì)應(yīng)的版本)
if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) {
customView.detailCalloutAccessoryView = [UISwitch new];
}
// 設(shè)置大頭針視圖可以被拖拽
customView.draggable = YES;
return customView;
return nil;
}
/**
* 選中大頭針視圖時(shí)調(diào)用這個(gè)方法
*
* @param mapView 地圖
* @param view 大頭針視圖
*/
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
NSLog(@"選中---%@", view.annotation.title);
}
/**
* 取消選中某個(gè)大頭針視圖
*
* @param mapView 地圖
* @param view 大頭針視圖
*/
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
NSLog(@"取消選中--%@", view.annotation.title);
}
/**
* 改變大頭針視圖拖拽狀態(tài)時(shí)調(diào)用
*
* @param mapView 地圖
* @param view 大頭針視圖
* @param newState 新?tīng)顟B(tài)
* @param oldState 老狀態(tài)
*/
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState
{
NSLog(@"%zd---%zd", oldState, newState);
}
@end