iOS定位服务系列之一:获取当前位置信息



    最近的一个业务涉及地图相关的服务,由于时间比较紧,所以借鉴了网上一些大神的代码,总算是交了差。现在回想起来,当初的自己是多么的窘迫,上网查看,铺天盖地的博文,每篇都是华丽丽的几大页,功能也都能满足要求,就是代码太多,全部复制粘贴吧,不合适,删减吧,又不能马上找到关键代码,不知道各自的依赖关系,只能根据自己的想象和经验修改后加入工程。

    如今空闲之余,本着打破沙锅的精神重新研究了地图与定位服务,现总结如下,希望给初始接触地图开发的人员以及将来的自己作为参考。

    我始终觉得,“最小系统”对于一个初学者非常重要。当初,我把百度地图嵌入的自己的APP中,在显示出地图的一刹那,我感到非常的兴奋,因为那是我花了几乎一整天时间的成果,现在想想,除了集成百度地图框架之外,也就几行代码就可以搞定的事情。所以,在这里我要从最基础的“最小系统”讲起,逐步在其上增加功能,尽量一个模块完成一个功能。


    啰嗦完了,开始正题:

    当今的生活中,手机已成为每个人的必备随身品,手机上越来越多的应用都使用了地图服务,而使用地图通常都离不开定位服务,所以在我的印象中,定位服务是地图的一个子功能,而实际上,在iOS中,定位与地图是两个完全不同的东东,它们有着相互独立的两套API(定位使用的类通常以CL开头,而地图服务的类以MK开头),可以只定位而不使用地图,也可以只用地图而不定位,只是他们结合很紧密,经常一起使用而已。

    在iOS中,定位服务基于CoreLocation框架,定位时主要使用CLLocationManager、CLLocationManagerDelegate和CLLocation,其中CLLocationManager类是定位服务管理类,他能够使我们获得设备的位置、高度、速度、运行方向等信息,也可以监控设备进出某个区域。而CLLocationManagerDelegate是CLLocationManager类的委托协议,CLLocation类封装了位置和高度信息。


//
//  ViewController.h
//  LocationTest011
//
//  Created by LZH on 15-4-2.
//  Copyright (c) 2015年 LZH. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>      //添加定位服务头文件(不可缺少)

@interface ViewController : UIViewController<CLLocationManagerDelegate>  //添加代理协议 CLLocationManagerDelegate

@end


//
//  ViewController.m
//  LocationTest011
//
//  Created by LZH on 15-4-2.
//  Copyright (c) 2015年 LZH. All rights reserved.
//

#import "ViewController.h"

@interface ViewController (){
    
    CLLocationManager *_locationManager;   //定位服务管理类
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    
    _locationManager = [[CLLocationManager alloc] init];     //创建CLLocationManager对象
    _locationManager.delegate = self;                        //设置代理,这样函数didUpdateLocations才会被回调
    
    [_locationManager startUpdatingLocation];                //启动定位服务
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{  //定位服务回调函数

    CLLocation *location = [locations lastObject];    //当前位置信息
    
    NSLog(@"经度:%f,纬度:%f,海拔:%f,航向:%f,行走速度:%f", location.coordinate.longitude, location.coordinate.latitude,location.altitude,location.course,location.speed);
}

@end


这便是关于定位服务的“最小系统”,关键代码只有7行,运行如下图:





    在包含有定位服务的应用第一次请求获得位置信息时,系统都会自动提示用户是否允许开启定位服务。关老师的书中提到,用户所在的位置是比较私密的信息,应用获取这些信息时,用户是有知情权和否定权的,如果应用在用户不知情的状况下,获得用户的位置信息,在某些国家是违法行为。
    此时点击“OK”,则定位开始,控制台不断打印出坐标信息,如果点击“Don't Allow”, 自然不会有任何信息打印,因为回调函数并没有被执行,所以无法获取到位置信息。


    CLLocation中除了经纬度信息外,还有海拔、航向、速度等信息,之所以后面的信息为0或-1,是因为模拟器上无法获取到这些信息,下面我们将此代码在真机上运行。
    然而当我将代码在iPhone6上跑起来时,却没有任何信息输出。鼓捣了半天仍没有信息输出,代理函数没有被回调,无法获取到位置信息。经查询API文档后,发现居然是iOS8系统自身的问题:在iOS8中,新增了2个与定位相关的方法:

- (void)requestAlwaysAuthorization __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0);
- (void)requestWhenInUseAuthorization __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0);

在使用定位服务时,必须显式调用上面的某个方法,同时,还需要在info.plist文件中声明下面的key:

NSLocationAlwaysUsageDescription     //对应方法 requestAlwaysAuthorization 
NSLocationWhenInUseUsageDescription  //对应方法 requestWhenInUseAuthorization 

这两个字段在info.plist文件中没有默认的值,完全需要手动输入,其值将会显示在提示用户授权使用定位功能的消息面


//
//  ViewController.m
//  LocationTest011
//
//  Created by LZH on 15-4-2.
//  Copyright (c) 2015年 LZH. All rights reserved.
//

#import "ViewController.h"

@interface ViewController (){
    
    CLLocationManager *_locationManager;   //定位服务管理类
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    
    _locationManager = [[CLLocationManager alloc] init];     //创建CLLocationManager对象
    _locationManager.delegate = self;                        //设置代理,这样函数didUpdateLocations才会被回调
    
    [_locationManager requestAlwaysAuthorization];           ///  新增的请求定位服务的语句
    
    [_locationManager startUpdatingLocation];                //启动定位服务
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{  //定位服务回调函数

    CLLocation *location = [locations lastObject];    //当前位置信息
    
    NSLog(@"经度:%f,纬度:%f,海拔:%f,航向:%f,行走速度:%f", location.coordinate.longitude, location.coordinate.latitude,location.altitude,location.course,location.speed);
}

@end

真机上运行:



终于看到了期待已久的提示框以及我们刚刚写的“Hello Kitty”提示语。
点击“允许”,控制台打印输出:



经纬度、海拔、航向,速度等信息都取到正确的值。

    如果刚刚点击了“不允许”,则以后都将无法获取到位置信息,直到重新安装应用。当然,也可以手动取消本应用定位服务的限制:点击 设置->隐私->定位服务,在下面的应用列表中找到自己的APP,更改“永不”设置即可。


    在iOS8中提供了更加人性化的定位服务选项:应用的定位服务不再仅仅是关闭或打开,iOS8中给定位服务的启用提供了三个选项:“永不”、“使用应用程序期间”和“始终”。同时,考虑到能耗问题,如果一款APP要求“始终”能在后台开启定位服务,iOS8不仅会在首次打开APP时主动向你询问,还会在日常使用中弹窗提醒你该APP一直在后台使用定位服务,并询问你是否继续允许。
    在iOS7及以前的版本中,如果在应用程序中使用定位服务,只要在程序中调用startUpdatingLocation方法,系统就会询问用户是否允许此应用使用定位服务,同时可以通过在info.plist文件中配置Privacy-Location Usage 
Description项来告诉用户使用的目的,与iOS8不同的是,这个配置是可选的。
    而在iOS8中配置配置项发生了变化,可以通过配置NSLocationAlwaysUsageDescription或者NSLocationWhenInUseUsageDescription来告诉用户使用定位服务的目的,但是不同的是这个配置是必须的,如果不进行配置则默认情况下应用无法使用定位服务,打开应用不会给出打开定位服务的提示,也无法获取到位置信息,除非安装后自己设置此应用的定位服务。同时,在应用程序中需要根据配置对requestAlwaysAuthorization或requestWhenInUseAuthorization方法进行请求。


好了,主题介绍完毕,现在补充些定位服务相关的知识:

使用iOS系统的iPhone、iPod touch及iPad都可以提供定位服务,而在iOS设备中能够提供以下3种不同的定位途径:

  1. GPS卫星定位:通过3-4颗GPS卫星来确定位置信息,优点是定位准确,缺点是耗电量大,而且不能够遮挡(即无法在室内使用);
  2. 蜂窝式移动电话基站定位:通过移动运营商的基站定位,优点是比GPS省点,缺点是误差较大
  3. WiFi定位:通过查询某个WiFi路由器的地理位置信息来定位,在三种方式中最为省电

    比较以上3种位置信息获取途径,GPS定位优点是:定位准确,覆盖面广,缺点是不能被遮挡且相当的费电;而蜂窝基站定位不仅误差比较大,且要耗费用户的流量;WiFi定位最经济实惠,缺点是定位信息是根据路由器来定,即使你出差去了外地,你的位置信息依然显示的时当初首次使用路由器定位时的位置信息。


那么我们在编程时究竟该采用哪种定位方式呢?

    这个其实完全不用担心,iOS不像Android系统那样,开发者在定位服务编程时可以指定采用哪种途径定位,iOS的API把底层这些细节屏蔽掉了,开发人员和用户并不知道当前设备是采用哪种方式进行定位的,iOS系统会根据设备的情况和周围的环境,采用一套最佳的解决方案。其核心思想是:如果能够接收GPS信号,则优先采用GPS定位,否则将采用WiFi定位,然后才会去考虑蜂窝基站定位。


GPS(Global Positioning System,全球定位系统)

    GPS是20世纪70年代由美国陆海空三军联合研制的新一代卫星定位系统,其前身是美国军方在1958年研制的子午仪卫星定位系统(Transit),主要目的是为陆海空三大领域提供实时、全天候和全球性的导航服务,并用于情报收集、核爆监测和应急通讯等一些军事目的,经过20余年的研究实验,耗资300亿美元,到1994年,全球覆盖率高达98%的24颗GPS卫星星座己布设完成。


BDS(BeiDou Navigation Satellite System,中国北斗卫星导航系统)

    BDS是中国自行研制的全球卫星导航系统,是继美国全球定位系统(GPS)、俄罗斯格洛纳斯卫星导航系统(GLONASS)之后第三个成熟的卫星导航系统。北斗卫星导航系统(BDS)和美国GPS、俄罗斯GLONASS、欧盟GALILEO,是联合国卫星导航委员会已认定的供应商。

    到2012年10月26日,中国已成功发射了16颗北斗导航卫星,这些导航卫星都分为军用频道和民用频道,军用频道是加密的且定位精度极高,民用频道定位精度要低一些。

    2014年11月23日,国际海事组织海上安全委员会审议通过了对北斗卫星导航系统认可的航行安全通函,这标志着北斗卫星导航系统正式成为全球无线电导航系统的组成部分,取得面向海事应用的国际合法地位。




 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值