iOS開發之地圖

在iOS開發中,地圖也是不少App都須要使用的功能。本文主要對iOS中的地圖知識點進行介紹。須要說明的是地圖看似很複雜,其實它僅僅是一個控件,就和UIButton、UITableView等同樣。本文代碼環境爲:Xcode 10.2git

1、理論知識

  • 地圖既然是控件,就能夠在StoryBoard和代碼中使用github

  • 地圖上若是想要顯示用戶的位置,必須與定位配合,那麼就須要建立定位管理器、設置權限等,能夠參考iOS開發之定位,同時須要設置地圖的屬性(代碼設置也能夠)以下圖 bash

    showUserLocation

2、準備工做

  1. 拖拽一個地圖到控制器View中
    StoryBoard中添加地圖控件
  2. 拖拽IBOutlet
  3. 聲明CLLocationManager
  4. 聲明權限
  5. 設置gpx數據

3、地圖基本使用

  • 實現功能:顯示地圖,而且顯示用戶所在的位置,點擊用戶的位置,顯示一個氣泡展現用戶的位置信息
  • 代碼
@interface ViewController ()<MKMapViewDelegate>

//地圖 不少屬性都在SB中配置了
@property (weak, nonatomic) IBOutlet MKMapView *map;

@property (strong, nonatomic) CLLocationManager *manager;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self showUserInfo];
    
}


// 若是想顯示用戶的位置 只須要下面三行代碼
-(void)showUser{
    
    _manager = [[CLLocationManager alloc]init];
    
    [_manager requestAlwaysAuthorization];
    
    _map.userTrackingMode = MKUserTrackingModeFollowWithHeading;
    
}


// 改變用戶藍點點擊後的氣泡信息
-(void)showUserInfo{
    
    _map.delegate = self;
    
    [self showUser];
    
}


//經過代理改變userLocation的標題實現更改信息
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
    
   
    CLLocation *location =  userLocation.location;
    
    CLGeocoder *geocoder = [[CLGeocoder alloc]init];
    
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        
        CLPlacemark *mark = placemarks.firstObject;
        
        userLocation.title = mark.locality;
        
        userLocation.subtitle = mark.thoroughfare;
  
    }];
}
@end
複製代碼
  • 效果
    實現效果

4、地圖縮放級別

  • 實現功能:在以前功能的基礎上實現地圖的任意視角(「縮放級別」)
  • 代碼
@interface ViewController ()<MKMapViewDelegate>

@property(nonatomic, strong) CLLocationManager *manager;

@property (weak, nonatomic) IBOutlet MKMapView *map;

@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];
   
    _manager = [[CLLocationManager alloc]init];
    
    [_manager requestAlwaysAuthorization];
    
    _map.showsUserLocation = YES;
    
    _map.delegate = self;
}

//如何經過定位到的位置 設置地圖的「縮放級別」?
//經過設置地圖的MKCoordinateRegion達到
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
    
    CLLocation *location = userLocation.location;
    
    //設置地圖顯示的「區域」
    
    //跨度,經過這個精細控制顯示的地圖視角
    MKCoordinateSpan span = MKCoordinateSpanMake(0.003, 0.003);
    
    //區域
    MKCoordinateRegion region = MKCoordinateRegionMake(location.coordinate, span);
    
    //讓地圖顯示設置的區域
    [_map setRegion:region];
    
}

@end
複製代碼
  • 效果
    實現效果

5、添加標註

  • 功能:點擊屏幕,能夠添加標註
  • 說明:添加標註分三步
    • 建立標註模型
    • 重寫地圖的代理方法,返回標註的樣式
    • 將標註添加到地圖
  • 代碼
    • 標註模型
@interface MyAnnotation : NSObject <MKAnnotation>
/**
 *  大頭針的位置
 */
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
/**
 *  主標題
 */
@property (nonatomic,  copy, nullable) NSString *title;
/**
 *  副標題
 */
@property (nonatomic,  copy, nullable) NSString *subtitle;
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate;

@end
複製代碼
  • 控制器
@interface ViewController ()<CLLocationManagerDelegate, MKMapViewDelegate>

@property(nonatomic, strong) CLLocationManager *manager;

@property (weak, nonatomic) IBOutlet MKMapView *map;

@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];
    
    _manager = [[CLLocationManager alloc]init];
    
    [_manager requestAlwaysAuthorization];
    
    _map.showsUserLocation = YES;
    
    _map.delegate = self;
}


//點擊地圖的任一位置 均可以插入一個標註,標註的標題和副標題顯示的是具體位置
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    
    //點擊屏幕產生的座標如何與地圖的經緯度進行轉換?
    
    //1.獲取點擊的座標
    CGPoint touchPoint = [touches.anyObject locationInView:self.map];
    
    //2.將點擊的座標轉換成經緯度
    CLLocationCoordinate2D coordinate =  [self.map convertPoint:touchPoint toCoordinateFromView:self.map];

    //3.添加標註
    MyAnnotation *annotation = [[MyAnnotation alloc]init];
    
    annotation.coordinate = coordinate;

    [self.map addAnnotation:annotation];
}


-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
    
    
    //判斷是否是用戶的數據模型 讓用戶位置的標註不同
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        
       return  nil;
    }
    
    //1.從重用池取
    MKMarkerAnnotationView *annotationView = (MKMarkerAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"abc"];
    
    //2.沒有的時候建立
    if(annotationView == nil) {
        
        annotationView = [[MKMarkerAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"abc"];
        
    }
    
    return  annotationView;
}


-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
    
    CLLocation *location = userLocation.location;
    
    //設置地圖顯示的「區域」
    
    //跨度
    MKCoordinateSpan span = MKCoordinateSpanMake(0.013, 0.013);
    
    //區域
    MKCoordinateRegion region = MKCoordinateRegionMake(location.coordinate, span);
    
    //讓地圖顯示設置的區域
    [_map setRegion:region];
    
}

@end
複製代碼
  • 效果
    實現效果

6、添加自定義標註

  • 實現功能:在前面的基礎上,自定義標註的樣式
  • 代碼:只須要更改上面的代理方法便可
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
    
    //判斷是否是用戶的數據模型 讓用戶位置的標註不同
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        
        return  nil;
    }
    
    //1.從重用池取MKAnnotationView
    MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"abc"];
    
    //2.沒有的時候建立
    if(annotationView == nil) {
        
        annotationView = [[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"abc"];
        
    }
     
    //設置標註的圖片
    int i =  arc4random() % 11;
    
    NSString *imgName = [NSString stringWithFormat:@"icon_map_cateid_%d", i];
    
    annotationView.image = [UIImage imageNamed:imgName];
    
    //左邊視圖
    annotationView.leftCalloutAccessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"left"]];
    
    //右邊視圖
    annotationView.rightCalloutAccessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"right"]];
    
    annotationView.canShowCallout = YES;

    return  annotationView;
}
複製代碼
  • 效果
    實現效果

7、案例代碼

GitHub地址dom

相關文章
相關標籤/搜索