IOS——地图与定位

要实现地图、导航功能,往须要先熟悉定位功能,在iOS中经过Core Location框架进⾏定位操做。Core Location⾃身能够单独使用,和地图开发框架MapKit彻底是独立的,可是往地图开发要配合定位框架使用。在Core Location 中主要包含了定位、地理编码(包括反编码)功能。git

Core Location的主要功能:
1.获取经纬度
2.地理编码(根据给定的地名,得到具体的位置信息(如经纬度、地址的全 称等))
3.反地利编码(根据给定的经纬度,得到具体的位置信息)github

各个类的做用: CLLocation:用于表示位置信息,包含地理坐标、海拔等信息,包含在CoreLoaction框架中。app

MKUserLocation:一个特殊的大头针,表示用户当前位置。框架

CLPlacemark:定位框架中地标类,封装了详细的地理信息。异步

MKPlacemark:相似于CLPlacemark,只是它在MapKit框架中,能够根据CLPlacemark建立MKPlacemark。ide

##一、定位的基本使用动画

导入MapKit框架,添加成员变量,签定MKMapViewDelegate协议 这里的MKMapView是使用故事板方式建立,在故事板里面连线设置的协议代理编码

#import "ViewController.h"
#import <MapKit/MapKit.h>
@interface ViewController ()<MKMapViewDelegate>

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

@property (strong, nonatomic) CLLocationManager *locationManager;

@end

设置地图的样式atom

/** 
     MKMapTypeStandard = 0, 平面地图
     MKMapTypeSatellite, 卫星地图
     MKMapTypeHybrid, 混合地图
     MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0),
     MKMapTypeHybridFlyover**/
   
    self.mapView.mapType = MKMapTypeStandard;

是否显示用户位置spa

self.mapView.showsUserLocation = YES;

因为目前苹果的iOS系统最新版本为9,苹果自iOS8上之后若是要使用定位服务,受权定位用户的位置,须要在info.plist文件中添加(如下二选一,两个都添加默认使用NSLocationWhenInUseUsageDescription):

  • NSLocationWhenInUseUsageDescription 容许在前台使用时获取GPS的描述
  • NSLocationAlwaysUsageDescription 容许永远可获取GPS的描述

判断当前设备版本大于iOS8之后的话执行里面的方法

if ([UIDevice currentDevice].systemVersion.floatValue >=8.0) {
        //持续受权
        [locationManager requestAlwaysAuthorization];
        //当用户使用的时候受权
        [locationManager requestWhenInUseAuthorization];
    }

或者使用这种方式,判断是否存在这个方法,若是存在就执行,没有的话就忽略

if ([CLLocationManager instanceMethodForSelector:@selector(requestWhenInUseAuthorization)]) {
        
        [self.locationManager requestWhenInUseAuthorization];
    }

初始化locationManger管理器对象

_locationManager = [[CLLocationManager alloc] init];

设置定位的精确度 kCLLocationAccuracyNearestTenMeters 精确到10米 kCLLocationAccuracyHundredMeters精确到100米kCLLocationAccuracyKilometer 精确到1000米 kCLLocationAccuracyThreeKilometers精确到3000米 kCLLocationAccuracyBest 设备使用电池供电时最高的精度 kCLLocationAccuracyBestForNavigation 导航状况下最高的精度,通常有外接电源时才能使用

_locationManager.desiredAccuracy = kCLLocationAccuracyBest;

多远距离更新位置

_locationManager.distanceFilter = 10;

MKMapViewDelegate协议方法:

地图加载完成

- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {
    
    NSLog(@"%s %f, %f",__func__, mapView.userLocation.coordinate.longitude, mapView.userLocation.coordinate.latitude);
}

用户位置更新后调用

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
    
    //设置中心点
    CLLocationCoordinate2D center = userLocation.location.coordinate;
    
    // 设置跨度,值越大,范围越大
    MKCoordinateSpan span = {0.01,0.01};
    
    // 设置地图显示的范围
    [self.mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];
    
}

##二、地图添加标注视图

在这里咱们使用长按手势添加标注

建立一个长按手势,并添加到mapView上面

UILongPressGestureRecognizer *longGest = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longGestAction:)];

[self.mapView addGestureRecognizer:longGest];

手势方法实现

- (void)longGestAction:(UILongPressGestureRecognizer *)longGest {
    
    // 一、获取触摸点所在地图上的CGPoint坐标
    CGPoint point = [longGest locationInView:self.mapView];
    
    // 二、将地图所在触摸点的坐标 CGPoint 转为对应的经纬度 CLLocationCoordinate2D
    CLLocationCoordinate2D coordinate2D = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
    
    if (longGest.state == UIGestureRecognizerStateBegan) {
        
        // 三、建立并添加一个标注视图到mapView上
        MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
        annotation.title = @"XXXX";
        annotation.coordinate = coordinate2D;
        annotation.subtitle = [NSString stringWithFormat:@"%f, %f",annotation.coordinate.latitude, annotation.coordinate.longitude];
        
        [self setGeocodeComplatHandle:^(NSString *a,NSString *b) {
            
            annotation.title = a;
            annotation.subtitle = b;
        }];
       //地理位置编码方法
       [self geocoder:coordinate2D];

        //四、将标注添加到地图上
        [self.mapView addAnnotation:annotation];
    }
    
}

##三、地理位置编码

添加一个标注,经过点击位置的经纬度得到标注位置的信息...

建立编码对象

@property (strong, nonatomic) CLGeocoder *geocoder;

建立一个block做为参数传递的方式

@property (strong, nonatomic) void(^geocodeComplatHandle)(NSString *, NSString *);

在手势方法里面调用[self geocoder:coordinate2D]方法传递一个经纬度进去

- (void)geocoder:(CLLocationCoordinate2D)coordinate2D {
    
    // 建立一个经纬度位置 CLLocation
    CLLocation *location = [[CLLocation alloc] initWithLatitude:coordinate2D.latitude longitude:coordinate2D.longitude];
    
    // 一、经过经纬度获取对应的地理位置,查询位置是一个异步操做
    [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        
        CLPlacemark *placemark = [placemarks lastObject];
        
        NSLog(@"%@ %@ %@",placemark.name, placemark.thoroughfare,placemark.subThoroughfare);
        
        // 将地理位置名称显示在标注视图上
        if (self.geocodeComplatHandle) {
            
            self.geocodeComplatHandle(placemark.name,placemark.thoroughfare);
        }
    }];
}

##四、地理位置反编码

经过地名得到经纬度

在页面输入搜索地点,点击搜索 搜索按钮方法

- (IBAction)search:(id)sender {
    
    [self.geocoder geocodeAddressString:self.searchText.text completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        
        CLPlacemark *placemark = placemarks[0];

        //建立并添加一个标注视图到mapView上
        MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
        annotation.coordinate = placemark.location.coordinate;
        //将标注添加到地图上
        [self.mapView addAnnotation:annotation];
       
    }];
}

##五、自定义标注视图

  • 添加标注视图时调用,这里能够自定义标注视图
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    
    NSLog(@"viewForAnnotation");
    
    // 判断是不是用户当前的位置标注
    if (![annotation isKindOfClass:[MKPointAnnotation class]]) {
        
        return nil;
    }
    
    static NSString *identifer = @"annotation";
    MKAnnotationView *annatationView = [mapView dequeueReusableAnnotationViewWithIdentifier:identifer];
    
    //大头针样式
    // MKPinAnnotationView *annatationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifer];
    
    if (!annatationView) {
        
        annatationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifer];
        
        //annatationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifer];
        
        // 是否显示辅助标注视图
        annatationView.canShowCallout = YES;
        
        // 设置大头针的颜色,前提是为MKPinAnnotationView类型
        // annatationView.pinTintColor = [UIColor orangeColor];
        
        //设置大头针出现的动画,前提是为MKPinAnnotationView类型
        //annatationView.animatesDrop = YES;
        
        // 使用图片做为标注
        annatationView.image = [UIImage imageNamed:@"icon"];
        
        // 是否能够拖拽
        annatationView.draggable = YES;
        
        // 设置标注视图的偏移
        annatationView.centerOffset = CGPointMake(0, -25);
        
        // 设置辅助视图的偏移
        annatationView.calloutOffset = CGPointMake(0, -10);
        //能够设置为UIImage,可是没有点击事件
        UIButton *leftView = [UIButton buttonWithType:UIButtonTypeCustom];
        [leftView setImage:[UIImage imageNamed:@"头像"] forState:UIControlStateNormal];
        leftView.tag = 100;
        leftView.frame = CGRectMake(0, 0, 50, 50);
        // 设置左边的辅助视图
        annatationView.leftCalloutAccessoryView = leftView;
        
        // 设置右边的辅助视图
        annatationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
        
    }
    
    return annatationView;
}
  • 点击标注视图时调用
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
    
    NSLog(@"didSelectAnnotationView");
}
  • 点击左右辅助视图时调用
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
    
    NSLog(@"%@",control);
}
  • 地图开始加载时调用
- (void)mapViewWillStartLoadingMap:(MKMapView *)mapView {
    
    NSLog(@"地图开始加载时调用");
}
  • 地图加载完成时调用
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {
    
    NSLog(@"地图加载完成时调用");
}
  • 地图加载失败时调用
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error {
    
    NSLog(@"地图加载失败时调用");
}
  • 地图显示的范围将要发生改变时调用
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
    
    NSLog(@"地图显示的范围将要发生改变时调用");
}
  • 地图显示的范围改变后调用
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    
    NSLog(@"地图显示的范围改变后调用");
}
  • 定位用户的位置失败
- (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error {
    
    NSLog(@"定位用户的位置失败");
}
  • 标注视图拖拽后调用
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
   fromOldState:(MKAnnotationViewDragState)oldState {
    
    /** 拖拽的状态
        MKAnnotationViewDragStateNone = 0, 没有拖拽
        MKAnnotationViewDragStateStarting, 开始拖拽
        MKAnnotationViewDragStateDragging, 正在拖拽
        MKAnnotationViewDragStateCanceling, 取消拖拽
        MKAnnotationViewDragStateEnding 结束拖拽
     **/
    
    NSLog(@"didChangeDragState");
}

Demo下载地址:

https://github.com/fuxinto/HfxDemo

相关文章
相关标签/搜索