iOS 定位和地图

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

一、定位

1.1 定位概要

要实现地图、导航功能,往往需要先熟悉定位功能,在iOS中通过Core Location框架进行定位操作。Core Location自⾝可以单独使用,和地图开发框架MapKit完全是独立的,但是往往地图开发要配合定位框架使用。在Core Location 中主要包含了定位、地理编码(包括反编码)功能。

Core Location的主要功能:

1.获取经纬度

2.地理编码(根据给定的地名,获得具体的位置信息(如经纬度、地址的全称等))
3.反地理编码(根据给定的经纬度,获得具体的位置信息)

1.2 iOS 定位功能的实现

导入MapKit框架

     #import 

签订MKMapViewDelegate协议 ,添加成员变量

 @interface ViewController () @property (nonatomic, strong) CLLocationManager* locationManager;@end

 

设置地图的样式

    MKMapTypeStandard = 0, 平面地图MKMapTypeSatellite :卫星云图 (中图)MKMapTypeHybrid :混合模式(普通地图覆盖于卫星云图之上 )MKMapTypeSatelliteFlyover: 3D立体卫星 (iOS9.0)MKMapTypeHybridFlyover: 3D立体混合 (iOS9.0)self.mapView.mapType = MKMapTypeStandard;

是否显示用户位置 

     self.mapView.showsUserLocation = YES;

授权定位用户的位置,需要在info.plist文件中添加(以下二选一,两个都添加默认使用NSLocationWhenInUseUsageDescription):

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

 

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

定位的精确度

kCLLocationAccuracyBestForNavigation // 最适合导航kCLLocationAccuracyBest; // 最好的kCLLocationAccuracyNearestTenMeters; // 10mkCLLocationAccuracyHundredMeters; // 100mkCLLocationAccuracyKilometer; // 1000mkCLLocationAccuracyThreeKilometers; // 3000m// 精确度越高, 越耗电, 定位时间越长_locationManager.desiredAccuracy = kCLLocationAccuracyBest;

每个多少米定位一次

_locationManager.distanceFilter = 10;

1.3 地理位置编码

地理编码(根据给定的地名,获得具体的位置信息(如经纬度、地址的全称等))

对应方法

  • 地理编码方法-(void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler


创建编码对象

@property (strong, nonatomic) CLGeocoder *geocoder;

创建一个block作为参数传递的方式

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

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

- (void)geocoder:(CLLocationCoordinate2D)coordinate2D {// 创建一个经纬度位置 CLLocationCLLocation *location = [[CLLocation alloc] initWithLatitude:coordinate2D.latitude longitude:coordinate2D.longitude];// 1、通过经纬度获取对应的地理位置,查询位置是一个异步操作[self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray * _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);}}];
}

1.4 地理位置反编码

对应方法

  • 反地理编码方法-(void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler

反地理编码(根据给定的经纬度,获得具体的位置信息)

- (IBAction)search:(id)sender {[self.geocoder geocodeAddressString:self.searchText.text completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {CLPlacemark *placemark = placemarks[0];//创建并添加一个标注视图到mapView上MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];annotation.coordinate = placemark.location.coordinate;//将标注添加到地图上[self.mapView addAnnotation:annotation];}];
}

二、地图

2.1 地图(MapKit的基本概念)

在iOS6以后,苹果不再使用苹果地图,⽽是使用苹果⾃己的地图。我们使用Core Location来获取⽤户的位置信息,MapKit则是⽤来显⽰具体的信息。其核心是MKMapView类的使用,我们可以设置地图显示方式,控制地图,可以在地图上添加标注。

2.2 地图类型

  •  MKMapTypeStandard : 平面地图
  • MKMapTypeSatellite :卫星云图 (中图)
  • MKMapTypeHybrid :混合模式(普通地图覆盖于卫星云图之上 )
  • MKMapTypeSatelliteFlyover: 3D立体卫星 (iOS9.0)
  • MKMapTypeHybridFlyover: 3D立体混合 (iOS9.0)

 

 MKMapViewDelegate协议方法

#pragma mark - // 地图加载完成
- (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];NSLog(@"用户位置发生改变");
}

2.3 MKMapView添加标注视图

使用长按手势添加标注,创建一个长按手势,添加到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 转为对应的经纬度 CLLocationCoordinate2DCLLocationCoordinate2D 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 *locationName1,NSString *locationName2) {annotation.title = loationName1;annotation.subtitle = locationName2;}];// 地理位置编码方法[self geocoder:coordinate2D];// 将标注添加到地图上[self.mapView addAnnotation:annotation];}}

三、自定义标注视图

3.1 步骤:

1.⾃定义实现MKAnnotation的类并重新coordinate,title,subtitle属性。

2.实现MKMapViewDelegate的- mapView:viewForAnnotation: 方法。

自定义标注视图功能实现:
用户位置发生改变后调用

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {CLLocationCoordinate2D center = userLocation.location.coordinate;MKCoordinateSpan span = {0.05,0.05};[mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES];
}

添加了标注视图后调用

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {NSLog(@"添加了标注视图后调用");
}

 添加标注视图时调用,这里可以自定义标注视图

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)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];

 是否显示辅助标注视图

     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);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];

点击标注视图时调用

- (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)newStatefromOldState:(MKAnnotationViewDragState)oldState {/** 拖拽的状态MKAnnotationViewDragStateNone = 0, 没有拖拽MKAnnotationViewDragStateStarting, 开始拖拽MKAnnotationViewDragStateDragging, 正在拖拽MKAnnotationViewDragStateCanceling, 取消拖拽MKAnnotationViewDragStateEnding 结束拖拽**/NSLog(@"didChangeDragState");
}

转载于:https://my.oschina.net/nieqing/blog/744068


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部