iOS開發(fā)-地圖開發(fā)(CoreLocation和MapKit))

地圖(CoreLocation和MapKit)

  • CoreLocation框架

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

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

2大框架

  • CoreLocation:用于地理定位,地理編碼區(qū)域監(jiān)聽等(著重功能實現(xiàn))
  • MapKit:用于地圖展示,例如大頭針,路線,覆蓋層展示等(著重界面展示)

CoreLocation框架的使用

CLLocationManager

  • CoreLocation框架中使用CLLocationManager對象來做用戶定位
  • 創(chuàng)建(初始化)
CLLocationManager *lM = [[CLLocationManager alloc] init];

  • 常用屬性
    • 每隔多少米定位一次
      @property(assign, nonatomic) CLLocationDistance distanceFilter;
    • 定位精確度(越精確就越耗電)
      @property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;
    • 朝向改變時,每隔多少度調用一次
      @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參數(shù)里面裝著CLLocation對象

    • 停止更新用戶位置- (void) stopUpdatingLocation;

    • 判斷定位功能是否可用(為了嚴謹起見,最好在使用定位功能前進行判斷)+ (BOOL)locationServicesEnabled;

    • 監(jiān)聽設備朝向 -(void)startUpdatingHeading(如試例代碼中的指南針的實現(xiàn))

    • 區(qū)域監(jiān)聽(監(jiān)聽進出某個區(qū)域) -(void)requestStateForRegion:region;

    //使用位置管理者,開始更新用戶位置
    // 默認只能在前臺獲取用戶位置,
    // 勾選后臺模式 location updates
    [self.lM startUpdatingLocation];

    //監(jiān)聽設備朝向
    [self.lM startUpdatingHeading];
   - 區(qū)域監(jiān)聽(監(jiān)聽進出某個區(qū)域)
   [self.lM requestStateForRegion:region];
  • 代理方法
    • 跟新位置后調用- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
    • 授權狀態(tài)改變時調用-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
    • 獲取手機朝向時調用
      -(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
    • 區(qū)域監(jiān)聽的代理方法
      • 進入?yún)^(qū)域時調用:-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
      • 離開區(qū)域時調用:-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
      • 監(jiān)聽是否在某個區(qū)域的狀態(tài):-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state
/**
*  更新到位置之后調用
*
*  @param manager   位置管理者
*  @param locations 位置數(shù)組
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
   NSLog(@"定位到了");
   
   // 拿到位置,做一些業(yè)務邏輯操作
   
   
   // 停止更新
//    [manager stopUpdatingLocation];
}
/**
 *  授權狀態(tài)發(fā)生改變時調用
 *
 *  @param manager 位置管理者
 *  @param status  狀態(tài)
 */
-(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;
    }
}
/**
 *  簡易指南針的實現(xiàn)
 *  手機朝向改變時調用
 *
 *  @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);
    }]; 
}

//區(qū)域監(jiān)聽的代理方法
// 進入?yún)^(qū)域
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
   NSLog(@"進入?yún)^(qū)域--%@", region.identifier);
}

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

//監(jiān)聽是否在某個區(qū)域的狀態(tài)
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
   //state的值
   //CLRegionStateUnknown,
   //CLRegionStateInside,
   //CLRegionStateOutside
   NSLog(@"%zd", state);   
}

CLLocation

  • CLLocation用來表示某個位置的地理信息,比如經(jīng)緯度,海拔等等
  • 常用屬性
    • @property(readonly, nonatomic) CLLocationCoordinate2D coordinate;
      經(jīng)緯度
    • @property(readonly, nonatomic) CLLocationDistance altitude;
      海拔
    • @property(readonly, nonatomic) CLLocationDirection course;
      路線,航向(取值范圍是0.0° ~ 359.9°,0.0°代表真北方向)
    • @property(readonly, nonatomic) CLLocationSpeed speed;
      移動速度(單位是m/s)
  • 常用方法
    • 計算兩個位置之間的距離:- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location

使用試例:根據(jù)移動方向打印出移動的方向和距離

/**
 *  CLLocationManager對象的代理方法,當用戶位置改變的時候調用
 *  更新到位置之后調用
 *
 *  @param manager   位置管理者
 *  @param locations 位置數(shù)組
 * is kind of
 */
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//    NSLog(@"定位到了");
    /**
     *  CLLocation 詳解
     *  coordinate : 經(jīng)緯度
     *  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地圖開發(fā)用戶隱私保護(授權)

ios6+

  • 當使用定位時,系統(tǒng)會自動彈出對話框讓用戶授權。
    - 一旦用戶選擇了不允許,意味著應用程序以后都無法使用定位。
  • 開發(fā)者可以在Info.plist中設置NSLocationUsageDescription說明定位的目的(Privacy - Location Usage Description)

ios8.0+

從ios8.0開始,蘋果進一步加強了對用戶隱私的保護。
  • 當app想訪問用戶的隱私時,系統(tǒng)不再自動彈出一個對話框讓用戶授權.
解決方案
  • (1)調用ios8.0的api。主動請求用戶授權
    • -(void)requestAlwaysAuthorization // 請求允許在前后臺都能獲取用戶位置的授權
    • -(void)requestWhenInUseAuthorization // 請求允許在前臺獲取用戶位置的授權(注意:當設置為前臺授權時,通過設置后臺模式:location updates后 也可以后臺獲取定位信息,但是屏幕上方會出現(xiàn)藍條)
  • (2)務必在info.plist文件中配置對應的鍵值, 否則以上請求授權的方法不生效
    • NSLocationAlwaysUsageDescription : 允許在前后臺獲取GPS的描述
    • NSLocationWhenInUseDescription : 允許在前臺獲取GPS的描述

ios9.0

  • ios9.0如果當前處于前臺授權狀態(tài),默認是不可以后臺獲取用戶位置。但可以設置以下屬性為YES,就可以繼續(xù)在后臺獲取位置,但是在屏幕上方會出現(xiàn)藍條
    • @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可以完成“地理編碼”和“反地理編碼”
    • 地理編碼:根據(jù)給定的地名,獲得具體的位置信息(比如經(jīng)緯度、地址的全稱等)
    • 反地理編碼:根據(jù)給定的經(jīng)緯度,獲得具體的位置信息
  • 對應方法
    • 地理編碼方法-(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對象

地理編碼的實現(xiàn)

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

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

    // 地理編碼方案一:直接根據(jù)地址進行地理編碼(返回結果可能有多個,因為一個地點有重名)
    [self.geoC geocodeAddressString:self.addressDetailTV.text completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
        // 包含區(qū),街道等信息的地標對象
        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];
    }];
    // 地理編碼方案二:根據(jù)地址和區(qū)域兩個條件進行地理編碼(更加精確)
//    [self.geoC geocodeAddressString:self.addressDetailTV.text inRegion:nil completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
//        // 包含區(qū),街道等信息的地標對象
//        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];
//    }];
}

反地理編碼的實現(xiàn)

// 反地理編碼
- (IBAction)decode {
    // 過濾空數(shù)據(jù)
    if ([self.latitudeTF.text length] == 0 || [self.longtitudeTF.text length] == 0) {
        return;
    }
    // 創(chuàng)建CLLocation對象
    CLLocation *location = [[CLLocation alloc] initWithLatitude:[self.latitudeTF.text doubleValue] longitude:[self.longtitudeTF.text doubleValue]];
    // 根據(jù)CLLocation對象進行反地理編碼
    [self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
        // 包含區(qū),街道等信息的地標對象
        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;
      區(qū)域
    • @property (nonatomic, readonly) NSDictionary *addressDictionary;詳細的地址信息
    • @property (nonatomic, readonly) NSString *name;
      地址名稱
    • @property (nonatomic, readonly) NSString *locality;
      城市

MapKit框架的使用

MapKit通過MKMapView來顯示地圖

  • 常用屬性
    • 地圖配型:mapType

      • MKMapTypeStandard :普通地圖(左圖)
      • MKMapTypeSatellite :衛(wèi)星云圖 (中圖)
      • MKMapTypeHybrid :混合模式(普通地圖覆蓋于衛(wèi)星云圖之上 )
      • MKMapTypeSatelliteFlyover: 3D立體衛(wèi)星 (iOS9.0)
      • MKMapTypeHybridFlyover: 3D立體混合 (iOS9.0)
    • 操作項

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

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

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

      • 設置地圖的中心點位置
        • @property (nonatomic) CLLocationCoordinate2D centerCoordinate;
        • -(void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated;
      • 設置地圖的顯示區(qū)域
        • @property (nonatomic) MKCoordinateRegion region;
        • -(void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated;

MKCoordinateRegion

  • MKCoordinateRegion是一個用來表示區(qū)域的結構體
typedef struct {
         CLLocationCoordinate2D center; // 區(qū)域的中心點位置
        MKCoordinateSpan span; // 區(qū)域的跨度
} MKCoordinateRegion;
  • MKCoordinateSpan
typedef struct {
    CLLocationDegrees latitudeDelta; // 緯度跨度
    CLLocationDegrees longitudeDelta; // 經(jīng)度跨度
} MKCoordinateSpan;

MKMapView的代理

  • -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation;
    • 一個位置更改默認只會調用一次,不斷監(jiān)測用戶的當前位置
    • 每次調用,都會把用戶的最新位置(userLocation參數(shù))傳進來
  • -(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
    • 地圖的顯示區(qū)域即將發(fā)生改變的時候調用
  • -(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
    • 地圖的顯示區(qū)域已經(jīng)發(fā)生改變的時候調用

MKUserLocation

  • @property (nonatomic, copy) NSString *title;
    顯示在大頭針上的標題

  • @property (nonatomic, copy) NSString *subtitle;
    顯示在大頭針上的子標題

  • @property (readonly, nonatomic) CLLocation *location;
    地理位置信息(大頭針釘在什么地方?)

大頭針

  • 添加大頭針

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

    • 移除一個大頭針
      -(void)removeAnnotation:(id <MKAnnotation>)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 <MKAnnotation>)annotation;
      根據(jù)傳進來的(id <MKAnnotation>)annotation參數(shù)創(chuàng)建并返回對應的大頭針控件
    • 注意:如果返回nil,顯示出來的大頭針就采取系統(tǒng)的默認樣式
      標識用戶位置的藍色發(fā)光圓點,它也是一個大頭針,當顯示這個大頭針時,也會調用代理方法
      因此,需要在代理方法中分清楚(id <MKAnnotation>)annotation參數(shù)代表自定義的大頭針還是藍色發(fā)光圓點
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    // 判斷annotation的類型
    if (![annotation isKindOfClass:[TestAnnotation class]]) return nil;
    
    // 創(chuàng)建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 <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;
      標注左邊顯示什么控件
    • @property (nonatomic, strong) UIView *detailCalloutAccessoryView
      標注下面顯示什么控件(iOS9.0)

MKPinAnnotationView

MKPinAnnotationView是MKAnnotationView的子類

MKPinAnnotationView比MKAnnotationView多了2個屬性

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

MKMapItem調用系統(tǒng)APP進行導航

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

    // 創(chuàng)建終點:根據(jù) CLPlacemark 地標對象創(chuàng)建 MKPlacemark 地標對象
    MKPlacemark *itemP2 = [[MKPlacemark alloc] initWithPlacemark:endPlacemark];
    MKMapItem *item2 = [[MKMapItem alloc] initWithPlacemark:itemP2];

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

                                };
    // 根據(jù) MKMapItem 數(shù)組 和 啟動參數(shù)字典 來調用系統(tǒng)地圖進行導航
    [MKMapItem openMapsWithItems:@[item1, item2] launchOptions:launchDic];
}

MKMapCamera地圖街景

    // 創(chuàng)建視角中心坐標
     CLLocationCoordinate2D center = CLLocationCoordinate2DMake(23.132931, 113.375924);
    // 創(chuàng)建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];
    // 設置截圖區(qū)域(在地圖上的區(qū)域,作用在地圖)
    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;
            // 將圖片保存到指定路徑(此處是桌面路徑,需要根據(jù)個人電腦不同進行修改)
            NSData *data = UIImagePNGRepresentation(snapshot.image);
            [data writeToFile:@"/Users/wangshunzi/Desktop/snap.png" atomically:YES];
        }
    }];
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375

推薦閱讀更多精彩內容