前言:

现在很多社交、电商、团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用和导航应用所特有的。的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式。例如你到了一个陌生的地方想要查找附近的酒店、超市等就可以打开软件搜索周边;类似的,还有很多团购软件可以根据你所在的位置自动为你推荐某些商品。总之,目前地图和定位功能已经大量引入到应用开发中。在产品研发中有两个专业术语需要大家知道:一是LBS(Location Based Service)基于定位的服务,二是SoLoMo(Social Local Mobile )社交本地的移动应用,这都是需要我们提供地图和定位服务。

在后面的课程里就和大家一起看一下iOS如何进行地图和定位开发。iOS系统为了方便我们开发,提供了地图服务的框架。除此之外,实际的开发工作中,我们常常会使用一些第三发的SDK来实现地图服务,主要有高德地图和百度地图,这些我们后在后面的几节中讲到。

地图功能的实现离不开定位服务,下面我们还是先来看一下iOS系统的定位功能是如何实现的。


1. 定位服务

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

我们先介绍一下iOS定位功能的实现。定位是一个很常用的功能,如一些地图软件打开之后如果用户允许软件定位的话,那么打开软件后就会自动锁定到当前位置,如果用户手机移动那么当前位置也会跟随着变化。要实现这个功能需要使用CoreLoaction中CLLocationManager类,首先看一下这个类的一些主要方法和属性:
类方法

说明

  • (BOOL)locationServicesEnabled;

是否启用定位服务,通常如果用户没有启用定位服务可以提示用户打开定位服务

  • (CLAuthorizationStatus)authorizationStatus;

定位服务授权状态,返回枚举类型:
kCLAuthorizationStatusNotDetermined: 用户尚未做出决定是否启用定位服务
kCLAuthorizationStatusRestricted: 没有获得用户授权使用定位服务,可能用户没有自己禁止访问授权
kCLAuthorizationStatusDenied :用户已经明确禁止应用使用定位服务或者当前系统定位服务处于关闭状态
kCLAuthorizationStatusAuthorizedAlways: 应用获得授权可以一直使用定位服务,即使应用不在使用状态
kCLAuthorizationStatusAuthorizedWhenInUse: 使用此应用过程中允许访问定位服务

属性 说明
desiredAccuracy 定位精度,枚举类型:kCLLocationAccuracyBest:最精确定位CLLocationAccuracy kCLLocationAccuracyNearestTenMeters:十米误差范围kCLLocationAccuracyHundredMeters:百米误差范围kCLLocationAccuracyKilometer:千米误差范围kCLLocationAccuracyThreeKilometers:三千米误差范围
distanceFilter 位置信息更新最小距离,只有移动大于这个距离才更新位置信息,默认为kCLDistanceFilterNone:不进行距离限制
对象方法 说明
startUpdatingLocation 开始定位追踪,开始定位后将按照用户设置的更新频率执行-(void)locationManager:(CLLocationManager*)manager didUpdateLocations:(NSArray *)locations;方法反馈定位信息
stopUpdatingLocation 停止定位追踪
startUpdatingHeading 开始导航方向追踪
stopUpdatingHeading 停止导航方向追踪
startMonitoringForRegion: 开始对某个区域进行定位追踪,开始对某个区域进行定位后。如果用户进入或者走出某个区域会调用- (void)locationManager:(CLLocationManager )manager didEnterRegion:(CLRegion )region和- (void)locationManager:(CLLocationManager )manager didExitRegion:(CLRegion )region代理方法反馈相关信息
stopMonitoringForRegion: 对某个区域进行定位追踪
requestWhenInUseAuthorization 请求获得应用使用时的定位服务授权,注意使用此方法前在要在info.plist中配置NSLocationWhenInUseUsageDescription
requestAlwaysAuthorization 请求获得应用一直使用定位服务授权,注意使用此方法前要在info.plist中配置NSLocationAlwaysUsageDescription
代理方法 说明
-(void)locationManager:(CLLocationManager )manager didUpdateLocations:(NSArray )locations; 位置发生改变后执行(第一次定位到某个位置之后也会执行)
-(void)locationManager:(CLLocationManager )manager didUpdateHeading:(CLHeading )newHeading; 导航方向发生变化后执行
-(void)locationManager:(CLLocationManager )manager didEnterRegion:(CLRegion )region 进入某个区域之后执行
-(void)locationManager:(CLLocationManager )manager didExitRegion:(CLRegion )region 走出某个区域之后执行

除了CLLocationManager之外,CLLocation类也是在我们做定位服务中经常看到的,CLLocation常用来表示某个位置的地理信息,比如经纬度、海拔高度等,当然他也给我们提供了计算两个地理位置之间间距的方法。下面我们看一下CLLocation的常用属性和方法:

方法 说明
-(instancetype)initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude; 初始化CLLocation,传入经纬度
-(instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate altitude:(CLLocationDistance)altitude horizontalAccuracy:(CLLocationAccuracy)hAccuracy verticalAccuracy:(CLLocationAccuracy)vAccuracy timestamp:(NSDate *)timestamp 初始化CLLocation,传入经纬度、定位精度和定位时间
-(instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate altitude:(CLLocationDistance)altitude horizontalAccuracy:(CLLocationAccuracy)hAccuracy verticalAccuracy:(CLLocationAccuracy)vAccuracy course:(CLLocationDirection)course speed:(CLLocationSpeed)speed timestamp:(NSDate *)timestamp; 初始化CLLocation,传入经纬度、定位精度和定位时间、定位路线、当前速度
-(CLLocationDistance) getDistanceFrom:(const CLLocation *); 计算两个点之间的距离
-(CLLocationDistance) distanceFromLocation:(const CLLocation *) 计算两个点之间的距离
属性 说明
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate; 经纬度,结构体,一般通过函数CLLocationCoordinate2DMake来创建
@property(readonly, nonatomic) CLLocationDistance altitude; 海拔
@property(readonly, nonatomic) CLLocationAccuracy horizontalAccuracy; 水平定位精度
@property(readonly, nonatomic) CLLocationAccuracy verticalAccuracy; 竖直定位精度
@property(readonly, nonatomic) CLLocationDirection course; 路线,航线(范围在0-359.9之间,0代表正北方向)
@property(readonly, nonatomic) CLLocationSpeed speed; 行走速度(m/s)
@property(readonly, nonatomic, copy) NSDate *timestamp; 时间标记

一般在开始定位之前,应用会向用户获取授权请求,在iOS7及以前的版本,如果在应用程序中使用定位服务只要在程序中调用startUpdatingLocation方法应用就会询问用户是否允许此应用是否允许使用定位服务,同时在提示过程中可以通过在info.plist中配置通过配置Privacy -Location Usage Description告诉用户使用的目的,当然这个配置是可选的。但是在iOS8中配置配置项发生了变化,我们可以通过配置NSLocationAlwaysUsageDescription或者 NSLocationWhenInUseUsageDescription来告诉用户使用定位服务的目的,并且注意这个配置是必须的,如果不进行配置则默认情况下应用无法使用定位服务,打开应用不会给出打开定位服务的提示,除非安装后自己设置此应用的定位服务。同时,在应用程序中需要根据配置对requestAlwaysAuthorization或locationServicesEnabled方法进行请求。
iOS8提供了更加人性化的定位服务选项。应用的定位服务不再仅仅是关闭或打开。现在,定位服务的启用提供了三个选项:永不、使用应用程序期间、和始终。同时,考虑到能耗问题,如果一款 App 要求始终能在后台开启定位服务,iOS 8 不仅会在首次打开 App 时主动向你询问,还会在日常使用中弹窗提醒你该 App 一直在后台使用定位服务,并询问你是否继续允许。
下面我们就来看一看iOS实现定位服务的具体步骤有哪些

  • 判断硬件是否开启了定位服务
  • 判断应用是否获取定位授权
  • 初始化定位管家的对象,注意需要设置为全局变量
  • 设置定位权限:iOS8的新特性,可以实现代理方法获取授权范围。注意需要修改plist文件NSLocationAlwaysUsageDescription/NSLocationWhenInUseUsageDescription。
  • 设置定位服务的属性。
  • 开启定位,实现代理方法,获取定位信息

示例代码

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>@interface ViewController ()<CLLocationManagerDelegate>// 定位服务管家
@property (nonatomic, strong)CLLocationManager *locationManager;@end@implementation ViewController
/*定位的实现1.导入框架 CoreLocation.framework2.导入库文件 #import <CoreLocation/CoreLocation.h>3.需要将定位管家 CLLocationManager 设置为全区变量1.判断硬件是否开启了定位服务2.初始化定位管家的对象,注意需要设置为全局变量3.判断定位服务授权状态,设置定位权限:iOS8的新特性,可以实现代理方法获取授权范围。注意需要修改plist文件 NSLocationAlwaysUsageDescription/NSLocationWhenInUseUsageDescription。4.设置定位服务的属性。5.开启定位,实现代理方法,获取定位信息*/- (void)viewDidLoad {[super viewDidLoad];// 1.判断硬件是否开启了定位服务BOOL isOpen = [CLLocationManager locationServicesEnabled];if (isOpen) {NSLog(@"定位服务已经打开");}else {NSLog(@"定位服务未开启");UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"你的定位服务未开启" message:@"请到setting开启定位服务" preferredStyle:UIAlertControllerStyleAlert];[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil]];[self presentViewController:alert animated:YES completion:nil];return;}// 判断应用是否获取定位授权NSInteger status = [CLLocationManager authorizationStatus];switch (status) {case 0:NSLog(@"kCLAuthorizationStatusNotDetermined--没有决定");//  用户从未选择过权限break;case 1:NSLog(@"kCLAuthorizationStatusRestricted--没有许可");// 无法使用定位服务,该状态用户无法改变break;case 2:NSLog(@"kCLAuthorizationStatusDenied--禁止使用");// 用户拒绝该应用使用定位服务,或是定位服务总开关处于关闭状态break;case 3:NSLog(@"kCLAuthorizationStatusAuthorizedAlways--始终允许");// 大致是用户同意程序在任意时候使用地理位置break;case 4:NSLog(@"kCLAuthorizationStatusAuthorizedWhenInUse--开启允许");// 大致是用户同意程序在可见时使用地理位置break;default:break;}// 2.初始化定位管家的对象,注意需要设置为全局变量,因为我们需要一直持有定位管家的对象,局部变量使用后即被销毁,在代理方法中,无法获得该对象及其属性,所以需要设置为全局变量[self locationManager];// 3.判断定位服务授权状态,设置定位权限:iOS8的新特性,可以实现代理方法获取授权范围。注意需要修改plist文件NSLocationAlwaysUsageDescription/NSLocationWhenInUseUsageDescription。if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {// 判断授权状态,在授权未确定是获取授权,一旦确定即无法在程序中修改,只能在settings中对app做授权设置if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {// 判断系统版本 大于8.0以上的版本可以手动获取授权// 请求始终允许访问,包括进入后台后 对应info设置:NSLocationAlwaysUsageDescription
//            [self.locationManager requestAlwaysAuthorization];// 请求当app打开时允许访问 对应info设置:NSLocationWhenInUseUsageDescription[self.locationManager requestWhenInUseAuthorization];// 注意:修改plist文件// NSLocationAlwaysUsageDescription---我想在后台还访问您的位置// NSLocationWhenInUseUsageDescription---我想在我的app开启的时候使用您的位置,可以吗?}}else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"你没有给该应用的定位服务授权" message:@"请到setting设置定位服务授权" preferredStyle:UIAlertControllerStyleAlert];[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil]];[self presentViewController:alert animated:YES completion:nil];return;// 没有给予授权}// 4.设置定位服务的属性。[self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];// 设置定位刷新距离,可以直接是由上面的参数指定[self.locationManager setDistanceFilter:100];//移动距离大于distanceFilter就会定位,否则不会,避免频繁的定位,消耗电量// 5.开启定位,实现代理方法,获取定位信息[self.locationManager startUpdatingLocation];
//    [self.locationManager stopUpdatingLocation];// 获取定位数据后调用// 开始追踪导航方向,[self.locationManager startUpdatingHeading];
//    [self.locationManager stopUpdatingHeading];// 停止追踪导航方向// 开启区域追踪,需要传入一个追踪区域CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(39.0, 116.0);CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:coordinate radius:1000 identifier:@"找到你了"];[self.locationManager startMonitoringForRegion:region];
}
// 懒加载定位管家
- (CLLocationManager *)locationManager {if (!_locationManager) {_locationManager = [[CLLocationManager alloc] init];_locationManager.delegate = self;// 设置定位服务的代理对象}return _locationManager;
}#pragma mark CLLocationManagerDelegate
/***  方法说明:当用户许可状态发生改变时,调用该方法**  @param status:用户的许可状态**  @return*/
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{NSLog(@"认证状态改变 status:%d",status);
}/***  方法说明:执行定位后调用该方法**  @param**  @return*/
- (void)locationManager:(CLLocationManager *)managerdidUpdateLocations:(NSArray *)locations {// 停止定位(省电措施:只要不想用定位服务,或者获取定位信息后,就马上停止定位服务)[self.locationManager stopUpdatingLocation];// 1.取出位置对象(数组中可能会有多个位置对象,取出第一个是最精确的)CLLocation *loc = [locations firstObject];// 2.取出经纬度 coordinate:位置坐标  course:方向CLLocationCoordinate2D coordinate = loc.coordinate;CLLocationDegrees longitude = coordinate.longitude;CLLocationDegrees latitude = coordinate.latitude;// 3.CLLocations的常用属性和方法/*horizontalAccuracy,用来得到水平上的精确度,它的大小就是定位精度的半径,单位为米。获得的不是用户设置的精度  而是最终定位的精度,如果值为-1,则说明此定位不可信。course 方向: 0 ~ 359.9 , 0 代表正北speed 速度:m/s获取两个位置之间的距离- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location*/NSLog(@"经度:%f \n 纬度:%f", longitude, latitude);NSLog(@"方向:%f \n 海拔:%f",loc.course, loc.altitude);NSLog(@"水平定位精度%f  竖直定位精度%f",loc.horizontalAccuracy,loc.verticalAccuracy);NSLog(@"速度:%f",loc.speed);// 计算2个经纬度之间的直线距离CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:40 longitude:116];CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:41 longitude:116];// 计算2个经纬度之间的直线距离CGFloat distance = [self countLineDistance:loc1 withLocation:loc2];NSLog(@"%f",distance);
}/***  计算2个经纬度之间的直线距离*/
- (double)countLineDistance:(CLLocation *)loc1 withLocation:(CLLocation *)loc2
{CLLocationDistance distance = [loc1 distanceFromLocation:loc2];return distance;
}/***  方法说明: 导航方向发生变化的时候执行此方法**  @param  newHeading 方向: 0 ~ 359.9 , 0 代表正北**  @return*/
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{NSLog(@"方向改变");
}- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{NSLog(@"进入到该区域");
}- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{NSLog(@"离开该区域");
}@end

使用定位功能时,有几点需要我们注意:

  • 定位频率和定位精度并不应当越精确越好,需要视实际情况而定,因为越精确越耗性能,也就越费电。
  • 定位成功后会根据设置情况频繁调用-(void)locationManager:(CLLocationManager )manager didUpdateLocations:(NSArray )locations方法,使用完定位服务后如果不需要实时监控应该立即关闭定位服务以节省资源,所以我们需要在合适的时候停止定位。
  • -(void)locationManager:(CLLocationManager )manager didUpdateLocations:(NSArray )locations方法返回一组地理位置对象数组,每个元素一个CLLocation代表地理位置信息(包含经度、纬度、海报、行走速度等信息),之所以返回数组是因为有些时候一个位置点可能包含多个位置。

2. 地理编码和反地理编码

除了提供位置跟踪功能之外,在定位服务中还包含CLGeocoder类用于处理地理编码和逆地理编码功能。这个功能的实现主要是由CLGeocoder类提供的。CLGeocoder最主要的两个方法就是

  • -(void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler;// 根据给定的位置(通常是地名)确定地理坐标(经、纬度)。
  • -(void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler; // 根据地理坐标(经、纬度)确定位置信息(街道、门牌等)。

在上面两个方法的方法中,当地理编码或是反编码结束时,会回调CLGeocodeCompletionHandler,当中传递给我们两个参数,一个NSArray,一个NSError。NSError是编码或者反编码错误的详情,数组中则存放着我们地理编码或是反地理编码后获取的地标信息,为什么是数组呢,因为我们可能查询到多个地标,比如“帝都”代表的地标就有多个。在CoreLocation框架中,地标是一个CLPlacemark的实例对象。下面我们先来看一下CLPlacemark的常用属性:

属性 说明
@property (nonatomic, readonly, copy, nullable) CLLocation *location; 地理坐标
@property (nonatomic, readonly, copy, nullable) CLRegion *region; 地理范围
@property (nonatomic, readonly, copy, nullable) NSTimeZone *timeZone 地标所在时区
@property (nonatomic, readonly, copy, nullable) NSString *name; 地名
@property (nonatomic, readonly, copy, nullable) NSString *thoroughfare; 街道
@property (nonatomic, readonly, copy, nullable) NSString *subThoroughfare; 街道相关信息,例如门牌等
@property (nonatomic, readonly, copy, nullable) NSString *locality; 城市
@property (nonatomic, readonly, copy, nullable) NSString *subLocality; 城市相关信息,例如标志性建筑
@property (nonatomic, readonly, copy, nullable) NSString *administrativeArea;
@property (nonatomic, readonly, copy, nullable) NSString *subAdministrativeArea; 其他行政区域信息
@property (nonatomic, readonly, copy, nullable) NSString *postalCode; 邮编
@property (nonatomic, readonly, copy, nullable) NSString *ISOcountryCode; 国家编码
@property (nonatomic, readonly, copy, nullable) NSString *country; 国家
@property (nonatomic, readonly, copy, nullable) NSString *inlandWater; 水源、湖泊
@property (nonatomic, readonly, copy, nullable) NSString *ocean; 海洋
@property (nonatomic, readonly, copy, nullable) NSArray *areasOfInterest; 关联的或利益相关的地标
@property (nonatomic, readonly, copy) NSDictionary *addressDictionary; 地理的详细信息 包含上面所有的数据

示例代码

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>@interface ViewController ()@property (nonatomic, strong)CLGeocoder *geocoder;//地理编码器#pragma mark - 地理编码 根据地区名称查询所在的经纬度坐标
@property (strong, nonatomic) IBOutlet UITextField *addressField;//输入地区名称
@property (strong, nonatomic) IBOutlet UILabel *longitudeLabel;//显示地区的经度
@property (strong, nonatomic) IBOutlet UILabel *latitudeLabel;//显示地区的纬度
@property (strong, nonatomic) IBOutlet UILabel *detailAddressLabel;//显示地区的详细信息#pragma mark - 反地理编码 根据经纬度获取对应的地区名
@property (strong, nonatomic) IBOutlet UITextField *reverseLongtitudeField;//查询地区的经度
@property (strong, nonatomic) IBOutlet UITextField *reverseLatitudeField;//查询地区的纬度
@property (strong, nonatomic) IBOutlet UILabel *reverseDetailAddressLabel;//查询的地区详细名称
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];//初始化地理编码器if (!_geocoder) {_geocoder = [[CLGeocoder alloc] init];}
}// 地理编码
- (IBAction)geocoder:(id)sender {//获取输入的城市名称NSString *address = self.addressField.text;if (address.length == 0) return;[self getCoordinateByAddress:address withBlock:^(CLPlacemark *pm) {// 设置经纬度self.latitudeLabel.text = [NSString stringWithFormat:@"%.2f", pm.location.coordinate.latitude];self.longitudeLabel.text = [NSString stringWithFormat:@"%.2f", pm.location.coordinate.longitude];// 设置具体地址self.detailAddressLabel.text = pm.name;} withfaild:^(NSError *error) {self.detailAddressLabel.text = @"你找的地址可能不存在,请重新输入";self.addressField.text = @"";}];
}- (void)getCoordinateByAddress:(NSString *)address withBlock:(void(^)(CLPlacemark *pm))block withfaild:(void(^)( NSError *error))faild{[_geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {if (error) { // 有错误(地址乱输入)faild(error);} else { // 编码成功// 取出最前面的地址(数组中可能存在过河产讯到的地址)CLPlacemark *pm = [placemarks firstObject];// 回调数据block (pm);NSLog(@"总共找到%ld个地址", placemarks.count);//遍历数组,获取所有查找到的城市for (CLPlacemark *pm in placemarks) {NSLog(@"-----地址开始----");// 枚举编译出得所有的地理信息[pm.addressDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {NSLog(@"%@:%@", key, obj);}];NSLog(@"-----地址结束----");}}}];
}- (IBAction)reverseGeocoder:(id)sender {// 1.包装位置,将输入的字符串设置为地理坐标CLLocationDegrees latitude = [self.reverseLatitudeField.text doubleValue];CLLocationDegrees longitude = [self.reverseLongtitudeField.text doubleValue];CLLocation *loc = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];[self getAddressByLocation:loc withBlock:^(CLPlacemark *pm) {// 设置具体地址self.reverseDetailAddressLabel.text = [NSString stringWithFormat:@"%@ %@ %@ %@ %@",pm.country,pm.locality,pm.subLocality,pm.thoroughfare,pm.subThoroughfare];} withFaild:^(NSError *error) {self.reverseDetailAddressLabel.text = @"你找的地址可能只在火星有!!!";}];
}- (void)getAddressByLocation:(CLLocation *)loc withBlock:(void(^)(CLPlacemark *pm))block withFaild:(void(^)(NSError *error))faild {// 2.反地理编码[_geocoder reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks, NSError *error) {if (error) { // 有错误(地址乱输入)faild (error);} else { // 编码成功// 取出最前面的地址CLPlacemark *pm = [placemarks firstObject];block (pm);NSLog(@"总共找到%ld个地址", placemarks.count);for (CLPlacemark *pm in placemarks) {NSLog(@"-----地址开始----");// 获取所有的地标信息[pm.addressDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {NSLog(@"%@:%@", key, obj);}];NSLog(@"-----地址结束----");}}}];
}
@end

地图与定位(一)定位服务相关推荐

  1. android ip 定位,IP定位-API文档-开发指南-Web服务 API | 高德地图API

    产品介绍 IP定位是一套简单的HTTP接口,根据用户输入的IP地址,能够快速的帮用户定位IP的所在位置. IP定位 2.0(推荐):支持IPV4和IPV6两种地址,还支持部分国外国家或地区的IP解析: ...

  2. 百度地图- - - 鹰眼轨迹- - - -实时定位

    2019独角兽企业重金招聘Python工程师标准>>> 最近看了下鹰眼轨迹sdk,写了个小demo,做个笔记,以便以后需要的时候可以参考下... 1.先将需要的sdk嵌入到工程中,直 ...

  3. android百度地图单点定位_Android百度地图实现搜索和定位及自定义图标绘制并点击时弹出泡泡...

    一.问题描述 上一次我们使用百度地图实现基本的定位功能,接下来我们继续实现搜索和定位,并使用LocationOverlay绘制定位位置,同时展示如何使用自定义图标绘制并点击时弹出泡泡 如图所示: 二. ...

  4. 第三方SDK:百度地图(二)定位 + 鹰眼轨迹

    #1 基础地图 + 基础定位# 可以看到地图的界面. 如图: Menu: <menu xmlns:android="http://schemas.android.com/apk/res ...

  5. 百度地图之地图显示和定位,获取定位的经纬度

    在百度地图api开放平台,把demo下载 把第三方的包粘贴到自己项目的libs包下(android-support-v4.jar这个包不要粘) 在百度开发平台创建项目,输入项目名, 从cmd中获取sh ...

  6. android studio高德地图的显示于定位(附带逆地理编码围栏)

    首先注册高德成为开发者(打开高德地图,点击底部的开发者平台),创建应用,按照要求填写相应信息 网站:http://lbs.amap.com/api/android-sdk/guide/create-p ...

  7. php调用百度地图定位,php用百度地图API进行IP定位和GPS定位

    /** * 根据地理坐标获取国家.省份.城市,及周边数据类(利用百度Geocoding API实现) * 百度密钥获取方法:http://lbsyun.baidu.com/apiconsole/key ...

  8. 百度地图实现普通地图、定位、周边搜索功能

    //--------------一下是普通地图的实现----------------------------------- 1:打开百度地图APi进去,如果没有注册过的需要注册,注册过的登录进入 2: ...

  9. 百度地图采集经纬度坐标数据定位的javascript实战开发(地理坐标拾取系统、地址定位点选插件、实时定位、数据导入、地理编码、位置纠偏)

    坐标采集 前言 1.百度地图地理坐标拾取系统 2.位置选择插件 百度地图经纬度选择插件 默认参数配置 3.数据导入 4.地理编码 爬取百度webAPI 返回参数 前端封装转换函数 5.手机GPS定位 ...

  10. 室内地图商场停车场室内定位导航拓展方案应用

    近几年来.室内位置信息在人们的日常生活中扮演着越来越关键的数据,定位服务市场发展迅速.定位服务需求量迅速增长.比如,医疗行业中重症病人跟踪监护,产房婴儿防盗,贵重医疗设备监控;商场人员定位,顾客消费习 ...

最新文章

  1. Entrust - Laravel 用户权限系统解决方案
  2. java文件保存异常_Java 实现把异常信息写入到文件中
  3. bsdiff php,Apk差分升级Android客户端和Node.js服务端实现
  4. 常见浏览器兼容性问题与解决方式
  5. Event-based Vision: A Survey——论文阅读笔记
  6. 道客巴巴vip账号共享2020_腾讯视频VIP怎么两个手机通用?
  7. photoshop问题
  8. linux 魔术分区,Parted Magic-Linux 中的分区魔术师
  9. 使用Entity Framework和Web API的ASP.NET Core Blazor CRUD
  10. 什么是Joint Escalation Team?
  11. zabbix---agent安装
  12. google ads 关联 firebase 进行广告投放配置
  13. 重启计算机之前无法刷新,更新完补丁不断提示是否重启电脑的解决方法
  14. PPT 将图片的白色部分透明化
  15. 华为交换机查看设备型号
  16. 绘制热力图seaborn.heatmap,cmap设置颜色的参数
  17. python 画高程图像
  18. Ubuntu16.04笔记本 安装R RStudio
  19. 天刀论剑显示服务器,天刀论剑系统全方位深入科普
  20. 微波辐射数据读取与处理

热门文章

  1. java IO、NIO、AIO详解
  2. 学术论文写作1——abstract,句型
  3. Unet++语义分割网络(网络结构分析+代码分析)
  4. 软考_法律法规与标准化知识
  5. 云主机装黑果实践(4):阿里轻量机上变色龙bootloader启动问题
  6. SP8266搭建简易web
  7. 计算机系双选会方案,黄山学院2018届毕业生就业双选会工作方案
  8. ftp服务器修改pasv,ftp服务器修改pasv
  9. ghost网络克隆功能实现【批量】计算机操作【系统的安装】,Ghost怎么网络克隆备份还原系统GhostCast教程...
  10. Synergistic Saliency and Depth Prediction for RGB-D Saliency Detection