iOS 地圖定位 地圖

joker_king發表於2018-12-20

地圖

準備工作

  • 匯入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
}
複製程式碼

建立一個地圖

  1. 在延展裡宣告一個地圖的屬性
@interface RootViewController ()<MKMapViewDelegate>
@property (strong, nonatomic)MKMapView *mapView;
@property (assign, nonatomic)CGRect frame;
@end
複製程式碼
  1. 把這個屬性寫成懶載入並將它新增檢視控制器的view上
-(MKMapView *)mapView{
    if (!_mapView) {
        _mapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
        [self.view addSubview:_mapView];
    }return _mapView;
}
複製程式碼
  1. 為了讓地圖適配螢幕的旋轉,我們需要重寫下面這個方法 這個方法的返回值是一個列舉型別,返回的是支援螢幕旋轉的方向
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;
}
複製程式碼
  1. 設定地圖的跟蹤屬性,以及使用的地圖型別
//使用者位置追蹤(使用者位置追蹤用於標記使用者當前位置,此時會呼叫定位服務)
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的時候大頭針保持系統的樣子
    }
}
複製程式碼

相關文章