iOS作地圖相關須要知道的Tips(二)—— CoreLocation和MapKit框架

1、地圖(CoreLocation和MapKit)

  • CoreLocation框架ios

    • CoreLocation
    • CLLocation
    • ios地圖開發的隱私保護(如何添加受權)
    • CLGeocoder
    • CLPlacemark
  • MapKit框架git

    • MKMapView
    • MKCoordinateRegion
    • MKMapView的代理
    • MKUserLocation
    • 大頭針
    • annotation
    • 自定義大頭針
    • MKAnnotationView
    • MKPinAnnotationView
    • MKMapItem調用系統APP進行導航
    • MKMapCamera地圖街景
    • MKMapSnapshotter地圖截圖

2、大框架

CoreLocation:用於地理定位,地理編碼區域監聽等(着重功能實現)
MapKit:用於地圖展現,例如大頭針,路線,覆蓋層展現等(着重界面展現)
複製代碼

CoreLocation框架的使用

CLLocationManager

CoreLocation框架中使用CLLocationManager對象來作用戶定位 建立(初始化)api

CLLocationManager *lM = [[CLLocationManager alloc] init];
複製代碼

經常使用屬性

  • 每隔多少米定位一次數組

    @property(assign, nonatomic) CLLocationDistance distanceFilter;
    複製代碼
  • 定位精確度(越精確就越耗電)bash

    @property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;
    複製代碼
  • 朝向改變時,每隔多少度調用一次app

    @property(assign, nonatomic) CLLocationDegrees headingFilter
    複製代碼
  • 每隔多米定位一次框架

    _lM.distanceFilter = 100;
    /**
        kCLLocationAccuracyBestForNavigation // 最適合導航
        kCLLocationAccuracyBest; // 最好的
        kCLLocationAccuracyNearestTenMeters; // 10m
        kCLLocationAccuracyHundredMeters; // 100m
        kCLLocationAccuracyKilometer; // 1000m
        kCLLocationAccuracyThreeKilometers; // 3000m
    */
    // 精確度越高, 越耗電, 定位時間越長
    _lM.desiredAccuracy = kCLLocationAccuracyBest;
     
    複製代碼

經常使用方法

  • 開始更新用戶位置
- (void)startUpdatingLocation;
複製代碼
  • 當調用了startUpdatingLocation方法後,就開始不斷地請求、刷新用戶的位置,一旦請求到用戶位置就會調用代理的下面方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
複製代碼

locations參數裏面裝着CLLocation對象ide

  • 中止更新用戶位置
- (void) stopUpdatingLocation;
複製代碼

判判定位功能是否可用(爲了嚴謹起見,最好在使用定位功能前進行判斷)ui

+ (BOOL)locationServicesEnabled;
複製代碼

監聽設備朝向編碼

-(void)startUpdatingHeading(如試例代碼中的指南針的實現)
複製代碼

區域監聽(監聽進出某個區域)

-(void)requestStateForRegion:region;
複製代碼
//使用位置管理者,開始更新用戶位置
    // 默認只能在前臺獲取用戶位置,
    // 勾選後臺模式 location updates
    [self.lM startUpdatingLocation];
複製代碼
//監聽設備朝向
    [self.lM startUpdatingHeading];
複製代碼
- 區域監聽(監聽進出某個區域)
   [self.lM requestStateForRegion:region];
複製代碼

代理方法

  • 更新位置後調用
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
複製代碼
  • 受權狀態改變時調用
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
複製代碼
  • 獲取手機朝向時調用
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
複製代碼
  • 區域監聽的代理方法

    • 進入區域時調用:
      -(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
      複製代碼
    • 離開區域時調用:
      -(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
      複製代碼
    • 監聽是否在某個區域的狀態:
      -(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state
      複製代碼
/**
*  更新到位置以後調用
*
*  @param manager   位置管理者
*  @param locations 位置數組
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
   NSLog(@"定位到了");
   
   // 拿到位置,作一些業務邏輯操做
   
   
   // 中止更新
//    [manager stopUpdatingLocation];
}
複製代碼
/**
 *  受權狀態發生改變時調用
 *
 *  @param manager 位置管理者
 *  @param status  狀態
 */
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
            // 用戶還未決定
        case kCLAuthorizationStatusNotDetermined:
        {
            NSLog(@"用戶還未決定");
            break;
        }
            // 問受限
        case kCLAuthorizationStatusRestricted:
        {
            NSLog(@"訪問受限");
            break;
        }
            // 定位關閉時和對此APP受權爲never時調用
        case kCLAuthorizationStatusDenied:
        {
            // 定位是否可用(是否支持定位或者定位是否開啓)
            if([CLLocationManager locationServicesEnabled])
            {
                NSLog(@"定位開啓,但被拒");
            }else
            {
                NSLog(@"定位關閉,不可用");
            }
//            NSLog(@"被拒");
            break;
        }
            // 獲取先後臺定位受權
        case kCLAuthorizationStatusAuthorizedAlways:
            //        case kCLAuthorizationStatusAuthorized: // 失效,不建議使用
        {
            NSLog(@"獲取先後臺定位受權");
            break;
        }
            // 得到前臺定位受權
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        {
            NSLog(@"得到前臺定位受權");
            break;
        }
        default:
            break;
    }
}
複製代碼
/**
 *  簡易指南針的實現
 *  手機朝向改變時調用
 *
 *  @param manager    位置管理者
 *  @param newHeading 朝向對象
 */
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
    /**
     *  CLHeading 
     *  magneticHeading : 磁北角度
     *  trueHeading : 真北角度
     */
    
    NSLog(@"%f", newHeading.magneticHeading);
    
    CGFloat angle = newHeading.magneticHeading;
    
    // 把角度轉弧度
    CGFloat angleR = angle / 180.0 * M_PI;
    
    // 旋轉圖片(指南針圖片)
    [UIView animateWithDuration:0.25 animations:^{
        self.compassView.transform = CGAffineTransformMakeRotation(-angleR);
    }]; 
}
複製代碼
//區域監聽的代理方法
// 進入區域
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
   NSLog(@"進入區域--%@", region.identifier);
}

// 離開區域
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
   NSLog(@"離開區域--%@", region.identifier);
}

//監聽是否在某個區域的狀態
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
   //state的值
   //CLRegionStateUnknown,
   //CLRegionStateInside,
   //CLRegionStateOutside
   NSLog(@"%zd", state);   
}
複製代碼

CLLocation

  • CLLocation用來表示某個位置的地理信息,好比經緯度,海拔等等

  • 經常使用屬性

    • 經緯度
    @property(readonly, nonatomic) CLLocationCoordinate2D coordinate;
    複製代碼
    • 海拔
    @property(readonly, nonatomic) CLLocationDistance altitude;
    複製代碼
    • 路線,航向(取值範圍是0.0° ~ 359.9°,0.0°表明真北方向)
    @property(readonly, nonatomic) CLLocationDirection course;
    複製代碼
    • 移動速度(單位是m/s)
    @property(readonly, nonatomic) CLLocationSpeed speed;
    複製代碼
  • 經常使用方法

    • 計算兩個位置之間的距離:
    - (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
    複製代碼
使用試例:根據移動方向打印出移動的方向和距離
/**
 *  CLLocationManager對象的代理方法,當用戶位置改變的時候調用
 *  更新到位置以後調用
 *
 *  @param manager   位置管理者
 *  @param locations 位置數組
 * is kind of
 */
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//    NSLog(@"定位到了");
    /**
     *  CLLocation 詳解
     *  coordinate : 經緯度
     *  altitude : 海拔
     *  course : 航向
     *  speed ; 速度
     */

    CLLocation *location = [locations lastObject];
    
//    NSLog(@"%@", location);
    
    /**
     *  場景演示:打印當前用戶的行走方向,偏離角度以及對應的行走距離,
        例如:」北偏東 30度  方向,移動了8米」
     */
    
    // 1. 獲取方向偏向
    NSString *angleStr = nil;
    
    switch ((int)location.course / 90) {
        case 0:
            angleStr = @"北偏東";
            break;
        case 1:
            angleStr = @"東偏南";
            break;
        case 2:
            angleStr = @"南偏西";
            break;
        case 3:
            angleStr = @"西偏北";
            break;
            
        default:
            angleStr = @"跑溝裏去了!!";
            break;
    }
    // 2. 偏向角度
    NSInteger angle = 0;
    angle = (int)location.course % 90;
    
    // 表明正方向
    if (angle == 0) {
        NSRange range = NSMakeRange(0, 1);
        angleStr = [NSString stringWithFormat:@"正%@", [angleStr substringWithRange:range]];
    }
    // 3.移動多少米
    double distance = 0;
    if(_oldL)
    {
        distance = [location distanceFromLocation:_oldL];
    }
    _oldL = location;
    // 4. 拼串 打印
    // 例如:」北偏東 30度  方向,移動了8米」
    NSString *noticeStr = [NSString stringWithFormat:@"%@%zd方向, 移動了%f米", angleStr, angle, distance];
    NSLog(@"%@", noticeStr);
}
複製代碼

ios地圖開發用戶隱私保護(受權)

ios6+

  • 當使用定位時,系統會自動彈出對話框讓用戶受權。
    • 一旦用戶選擇了不容許,意味着應用程序之後都沒法使用定位。
  • 開發者能夠在Info.plist中設置NSLocationUsageDescription說明定位的目的(Privacy - Location Usage Description)

ios8.0+

  • 從ios8.0開始,蘋果進一步增強了對用戶隱私的保護。

  • 當app想訪問用戶的隱私時,系統再也不自動彈出一個對話框讓用戶受權.

解決方案

  • (1)調用ios8.0的api。主動請求用戶受權

    • -(void)requestAlwaysAuthorization // 請求容許在先後臺都能獲取用戶位置的受權
    • -(void)requestWhenInUseAuthorization // 請求容許在前臺獲取用戶位置的受權(注意:當設置爲前臺受權時,經過設置後臺模式:location updates後 也能夠後臺獲取定位信息,可是屏幕上方會出現藍條)
  • (2)務必在info.plist文件中配置對應的鍵值, 不然以上請求受權的方法不生效

    • NSLocationAlwaysUsageDescription : 容許在先後臺獲取GPS的描述
    • NSLocationWhenInUseDescription : 容許在前臺獲取GPS的描述

ios9.0

  • ios9.0若是當前處於前臺受權狀態,默認是不能夠後臺獲取用戶位置。但能夠設置如下屬性爲YES,就能夠繼續在後臺獲取位置,可是在屏幕上方會出現藍條

    • @property(assign, nonatomic) BOOL allowsBackgroundLocationUpdates
    • 使用注意:必須設置對應的後臺模式:location updates
  • ios9.0能夠單次請求用戶位置

    • -(void)requestLocation
    • -(void)locationManager:(nonnull CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations // 成功調用
    • -(void)locationManager:(nonnull CLLocationManager *)manager didFailWithError:(nonnull NSError *)error // 失敗調用

CLGeocoder

  • 使用CLGeocoder能夠完成「地理編碼」和「反地理編碼」

    • 地理編碼:根據給定的地名,得到具體的位置信息(好比經緯度、地址的全稱等)
    • 反地理編碼:根據給定的經緯度,得到具體的位置信息
  • 對應方法

    • 地理編碼方法
    -(void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler;
    複製代碼
    • 反地理編碼方法
    -(void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;
    複製代碼
  • CLGeocodeCompletionHandler:反地理編碼完成時,就會調用CLGeocodeCompletionHandler

    • typedef void (^CLGeocodeCompletionHandler)(NSArray *placemarks, NSError *error);

      • error :當編碼出錯時(好比編碼不出具體的信息)有值
      • placemarks :裏面裝着CLPlacemark對象

地理編碼的實現

// 地理編碼
- (IBAction)geoCoder {

    //當傳入的值爲0時直接返回
    if ([self.addressDetailTV.text length] == 0) {
        return;
    }

    // 地理編碼方案一:直接根據地址進行地理編碼(返回結果可能有多個,由於一個地點有重名)
    [self.geoC geocodeAddressString:self.addressDetailTV.text completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
        // 包含區,街道等信息的地標對象
        CLPlacemark *placemark = [placemarks firstObject];
        // 城市名稱
//        NSString *city = placemark.locality;
        // 街道名稱
//        NSString *street = placemark.thoroughfare;
        // 全稱
        NSString *name = placemark.name;
        self.addressDetailTV.text = [NSString stringWithFormat:@"%@", name];
        self.latitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
        self.longtitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
    }];
    // 地理編碼方案二:根據地址和區域兩個條件進行地理編碼(更加精確)
//    [self.geoC geocodeAddressString:self.addressDetailTV.text inRegion:nil completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
//        // 包含區,街道等信息的地標對象
//        CLPlacemark *placemark = [placemarks firstObject];
//        self.addressDetailTV.text = placemark.description;
//        self.latitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
//        self.longtitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
//    }];

    

    // 地理編碼方案三:
//    NSDictionary *addressDic = @{
//                                 (__bridge NSString *)kABPersonAddressCityKey : @"北京",
//                                 (__bridge NSString *)kABPersonAddressStreetKey : @"棠下街"
//                                 };
//    [self.geoC geocodeAddressDictionary:addressDic completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
//        CLPlacemark *placemark = [placemarks firstObject];
//        self.addressDetailTV.text = placemark.description;
//        self.latitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
//        self.longtitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
//    }];
}
複製代碼

反地理編碼的實現

// 反地理編碼
- (IBAction)decode {
    // 過濾空數據
    if ([self.latitudeTF.text length] == 0 || [self.longtitudeTF.text length] == 0) {
        return;
    }
    // 建立CLLocation對象
    CLLocation *location = [[CLLocation alloc] initWithLatitude:[self.latitudeTF.text doubleValue] longitude:[self.longtitudeTF.text doubleValue]];
    // 根據CLLocation對象進行反地理編碼
    [self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
        // 包含區,街道等信息的地標對象
        CLPlacemark *placemark = [placemarks firstObject];
        // 城市名稱
//        NSString *city = placemark.locality;
        // 街道名稱
//        NSString *street = placemark.thoroughfare;
        // 全稱
        NSString *name = placemark.name;
        self.addressDetailTV.text = [NSString stringWithFormat:@"%@", name];
    }];

}
複製代碼

CLPlacemark

  • CLPlacemark的字面意思是地標,封裝詳細的地址位置信息 經常使用屬性

    • 地理位置
    @property (nonatomic, readonly) CLLocation *location;
    複製代碼
    • 區域
    @property (nonatomic, readonly) CLRegion *region;
    複製代碼
    • 詳細的地址信息
    @property (nonatomic, readonly) NSDictionary *addressDictionary;
    複製代碼
    • 地址名稱
    @property (nonatomic, readonly) NSString *name;
    複製代碼
    • 城市
    @property (nonatomic, readonly) NSString *locality;
    複製代碼

MapKit框架的使用

MapKit經過MKMapView來顯示地圖

  • 經常使用屬性

    • 地圖配型:mapType

      • MKMapTypeStandard :普通地圖(左圖)
      • MKMapTypeSatellite :衛星雲圖 (中圖)
      • MKMapTypeHybrid :混合模式(普通地圖覆蓋於衛星雲圖之上 )
      • MKMapTypeSatelliteFlyover: 3D立體衛星 (iOS9.0)
      • MKMapTypeHybridFlyover: 3D立體混合 (iOS9.0)
  • 操做項

    • 是否可縮放 zoomEnabled
    • 是否可滾動 scrollEnabled
    • 是否可旋轉 rotateEnabled
  • 顯示項

    • 是否顯示指南針 showsCompass (iOS9.0)
    • 是否顯示比例尺 showsScale (iOS9.0)
    • 是否顯示交通 showsTraffic (iOS9.0)
    • 是否顯示建築 showsBuildings
  • 跟蹤顯示用戶的位置(ios8-地圖不會自動滾到用戶所在的位置,ios8+地圖會自動放大到合適比例,並顯示出用戶位置)

    • MKUserTrackingModeNone :不跟蹤用戶的位置
    • MKUserTrackingModeFollow :跟蹤並在地圖上顯示用戶的當前位置
    • MKUserTrackingModeFollowWithHeading :跟蹤並在地圖上顯示用戶的當前位置,地圖會跟隨用戶的前進方向進行旋轉
  • 設置地圖顯示的區域和位置

    • 設置地圖的中心點位置

      • @property (nonatomic) CLLocationCoordinate2D centerCoordinate;
      • -(void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated;
    • 設置地圖的顯示區域

      • @property (nonatomic) MKCoordinateRegion region;
      • -(void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated;

MKCoordinateRegion

  • MKCoordinateRegion是一個用來表示區域的結構體
typedef struct {
         CLLocationCoordinate2D center; // 區域的中心點位置
        MKCoordinateSpan span; // 區域的跨度
} MKCoordinateRegion;
複製代碼
  • MKCoordinateSpan
typedef struct {
    CLLocationDegrees latitudeDelta; // 緯度跨度
    CLLocationDegrees longitudeDelta; // 經度跨度
} MKCoordinateSpan;
複製代碼

MKMapView的代理

  • -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation;

    • 一個位置更改默認只會調用一次,不斷監測用戶的當前位置
    • 每次調用,都會把用戶的最新位置(userLocation參數)傳進來
  • -(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated;

    • 地圖的顯示區域即將發生改變的時候調用
  • -(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;

    • 地圖的顯示區域已經發生改變的時候調用

MKUserLocation

  • @property (nonatomic, copy) NSString *title;
    • 顯示在大頭針上的標題
  • @property (nonatomic, copy) NSString *subtitle;
    • 顯示在大頭針上的子標題
  • @property (readonly, nonatomic) CLLocation *location;
    • 地理位置信息(大頭針釘在什麼地方?)

大頭針

  • 添加大頭針

    • 添加一個大頭針
      • -(void)addAnnotation:(id )annotation;
    • 添加多個大頭針
      • -(void)addAnnotations:(NSArray *)annotations;
  • 移除大頭針

    • 移除一個大頭針
      • -(void)removeAnnotation:(id )annotation;
    • 移除多個大頭針
      • -(void)removeAnnotations:(NSArray *)annotations;

annotation

  • 大頭針模型對象
#import <MapKit/MapKit.h>

@interface TestAnnotation : NSObject <MKAnnotation>
/** 座標位置 */
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
/** 標題 */
@property (nonatomic, copy) NSString *title; 
/** 子標題 */
@property (nonatomic, copy) NSString *subtitle; 
@end
複製代碼

自定義大頭針

  • 設置MKMapView代理

    • -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation;
      • 根據傳進來的(id )annotation參數建立並返回對應的大頭針控件
      • 注意:若是返回nil,顯示出來的大頭針就採起系統的默認樣式
      • 標識用戶位置的藍色發光圓點,它也是一個大頭針,當顯示這個大頭針時,也會調用代理方法
      • 所以,須要在代理方法中分清楚(id )annotation參數表明自定義的大頭針仍是藍色發光圓點
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    // 判斷annotation的類型
    if (![annotation isKindOfClass:[TestAnnotation class]]) return nil;
    
    // 建立MKAnnotationView
    static NSString *ID = @"tuangou";
    MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:ID];
    if (annoView == nil) {
        annoView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID];
        annoView.canShowCallout = YES;
    }
複製代碼

MKAnnotationView

地圖上的大頭針控件是MKAnnotationView

  • 屬性

    • @property (nonatomic, strong) id annotation;
      • 大頭針模型
    • @property (nonatomic, strong) UIImage *image;
      • 顯示的圖片
    • @property (nonatomic) BOOL canShowCallout;
      • 是否顯示標註
    • @property (nonatomic) CGPoint calloutOffset;
      • 標註的偏移量
    • @property (strong, nonatomic) UIView *rightCalloutAccessoryView;
      • 標註右邊顯示什麼控件
    • @property (strong, nonatomic) UIView *leftCalloutAccessoryView;
      • 標註左邊顯示什麼控件
    • @property (nonatomic, strong) UIView *detailCalloutAccessoryView
      • 標註下面顯示什麼控件(iOS9.0)

MKPinAnnotationView

MKPinAnnotationView是MKAnnotationView的子類

  • MKPinAnnotationView比MKAnnotationView多了2個屬性

    • @property (nonatomic) MKPinAnnotationColor pinColor;
      • 大頭針顏色
    • @property (nonatomic) BOOL animatesDrop;
      • 大頭針第一次顯示時是否從天而降

MKMapItem調用系統APP進行導航

// 根據兩個地標對象進行調用系統導航
- (void)beginNavWithBeginPlacemark:(CLPlacemark *)beginPlacemark andEndPlacemark:(CLPlacemark *)endPlacemark
{
    // 建立起點:根據 CLPlacemark 地標對象建立 MKPlacemark 地標對象
    MKPlacemark *itemP1 = [[MKPlacemark alloc] initWithPlacemark:beginPlacemark];
    MKMapItem *item1 = [[MKMapItem alloc] initWithPlacemark:itemP1];

    // 建立終點:根據 CLPlacemark 地標對象建立 MKPlacemark 地標對象
    MKPlacemark *itemP2 = [[MKPlacemark alloc] initWithPlacemark:endPlacemark];
    MKMapItem *item2 = [[MKMapItem alloc] initWithPlacemark:itemP2];

    NSDictionary *launchDic = @{
                                // 設置導航模式參數
                                MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
                                // 設置地圖類型
                                MKLaunchOptionsMapTypeKey : @(MKMapTypeHybridFlyover),
                                // 設置是否顯示交通
                                MKLaunchOptionsShowsTrafficKey : @(YES),

                                };
    // 根據 MKMapItem 數組 和 啓動參數字典 來調用系統地圖進行導航
    [MKMapItem openMapsWithItems:@[item1, item2] launchOptions:launchDic];
}
複製代碼

MKMapCamera地圖街景

// 建立視角中心座標
     CLLocationCoordinate2D center = CLLocationCoordinate2DMake(23.132931, 113.375924);
    // 建立3D視角
    MKMapCamera *camera = [MKMapCamera cameraLookingAtCenterCoordinate:center fromEyeCoordinate:CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001) eyeAltitude:1];
    // 設置到地圖上顯示
    self.mapView.camera = camera;
複製代碼

MKMapSnapshotter地圖截圖

// 截圖附加選項
    MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
    // 設置截圖區域(在地圖上的區域,做用在地圖)
    options.region = self.mapView.region;
//    options.mapRect = self.mapView.visibleMapRect;

    // 設置截圖後的圖片大小(做用在輸出圖像)
    options.size = self.mapView.frame.size;
    // 設置截圖後的圖片比例(默認是屏幕比例, 做用在輸出圖像)
    options.scale = [[UIScreen mainScreen] scale];

    MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
    [snapshotter startWithCompletionHandler:^(MKMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
        if (error) {
            NSLog(@"截圖錯誤:%@",error.localizedDescription);
        }else
        {
            // 設置屏幕上圖片顯示
            self.snapshootImageView.image = snapshot.image;
            // 將圖片保存到指定路徑(此處是桌面路徑,須要根據我的電腦不一樣進行修改)
            NSData *data = UIImagePNGRepresentation(snapshot.image);
            [data writeToFile:@"/Users/wangshunzi/Desktop/snap.png" atomically:YES];
        }
    }];
複製代碼

原文地址:iOS開發-地圖開發(CoreLocation和MapKit))

相關文章
相關標籤/搜索