要实现地图、导航功能,往须要先熟悉定位功能,在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下载地址: