iOS定位示例与原理

来源:互联网 发布:同花顺官方炒股软件 编辑:程序博客网 时间:2024/04/25 07:36


定位示例:

功能与效果

运行效果如下图:两个标签实时显示位置信息,也就是经纬度;点击按钮可以将当前位置设定为目的地;设定目的地之后,目的地经纬度会显示在最下面,同时当前位置到目的地间的距离将会实时显示在中间位置。

Core Location是iOS SDK中一个提供设备位置的框架。可以使用三种技术来获取位置:GPS、蜂窝或WiFi。在这些技术中,GPS最为精准,如果有GPS硬件,Core Location将优先使用它。如果设备没有GPS硬件(如WiFi iPad)或使用GPS获取当前位置时失败,Core Location将退而求其次,选择使用蜂窝或WiFi。Core Location的大多数功能是由位置管理器(CLLocationManager)提供的,可以使用位置管理器来指定位置更新的频率和精度,以及开始和停止接收这些更新。


例程源码:

//  ViewController.m

//  LocationAlert

//

//  Created by *** on 25/11/15.

//  Copyright (c) 2015 . All rights reserved.

//


#import "ViewController.h"

#import <CoreLocation/CoreLocation.h>


@interface ViewController ()<CLLocationManagerDelegate>

@property (weak, nonatomic) IBOutletUILabel *longitudeLabel;

@property (weak, nonatomic) IBOutletUILabel *latitudeLabel;

@property (weak, nonatomic) IBOutletUILabel *distanceLabel;

@property (weak,nonatomic) IBOutletUILabel *destinationLongitude;

@property (weak, nonatomic) IBOutletUILabel *destinationLatitude;


@property (strong,nonatomic) CLLocationManager *locationManager;

@property (strong,nonatomic) CLLocation *currentPoint;

@property (strong,nonatomic) CLLocation *destinationPoint;


@end


@implementation ViewController


- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    self.locationManager = [[CLLocationManageralloc] init];

    self.locationManager.delegate =self;

    self.locationManager.desiredAccuracy =kCLLocationAccuracyBest;//定位精度,这里选择最高精度

    self.locationManager.distanceFilter = kCLHeadingFilterNone;//设置更新频率,水平移动距离达到设定的距离才调用委托函数更新数据,这里选择None,表示任何变动都更新,默认也是None

    

    if (![CLLocationManagerlocationServicesEnabled]) {//检测设备是否可以提供定位功能

        NSLog(@"%i",[CLLocationManagerlocationServicesEnabled]);//

        return;//若不能提供定位功能,直接返回

    }

    

    /**

     *用户授权请求

     *requestAlwaysAuthorization只要app在运行,请求允许使用定位服务

     *requestWhenInUseAuthorization,只有app在前台运行时,请求允许使用定位服务

     *需要注意的是,要在plist文件中进行键值的配置,前者是NSLocationAlwaysUsageDescription

     *后者是:NSLocationWhenInUseUsageDescription

     *若没有对应的键值配置,定位服务无法启动

     */

    [self.locationManagerrequestAlwaysAuthorization];

    self.distanceLabel.hidden =YES;

}


- (void)didReceiveMemoryWarning {

    [superdidReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


#pragma mark - Button Pressed

/**

 * 选择目的地

 * 将当前的经纬度设定为目的地的经纬度

 */

- (IBAction)chooseDestinationPressed:(id)sender{

    NSString *desLongitudeStr = [NSStringstringWithFormat:@"%g\u00B0",

                                self.currentPoint.coordinate.longitude];

    self.destinationLongitude.text = desLongitudeStr;

    

    NSString *desLatitudeStr = [NSStringstringWithFormat:@"%g\u00B0",

                                 self.currentPoint.coordinate.latitude];

    self.destinationLatitude.text = desLatitudeStr;

    

    self.distanceLabel.hidden =NO;

    

    self.destinationPoint =self.currentPoint;

}


#pragma mark - CLLocationManagerDelegate Methods


- (void)locationManager:(CLLocationManager *)manager

didChangeAuthorizationStatus:(CLAuthorizationStatus)status {

    NSLog(@"Authorization status changed to %d", status);

    switch (status) {

        casekCLAuthorizationStatusAuthorizedAlways:

        casekCLAuthorizationStatusAuthorizedWhenInUse:

            [self.locationManagerstartUpdatingLocation];

            break;

            

        casekCLAuthorizationStatusNotDetermined:

        casekCLAuthorizationStatusRestricted:

        casekCLAuthorizationStatusDenied:

            [self.locationManagerstopUpdatingLocation];

            break;

    }

}

- (void)locationManager:(CLLocationManager *)manager

       didFailWithError:(NSError *)error {

    NSString *errorType = error.code ==kCLErrorDenied ? @"Access Denied"

    : [NSString stringWithFormat:@"Error %ld", (long)error.code,nil];

    UIAlertController *alertController =

    [UIAlertControlleralertControllerWithTitle:@"Location Manager Error"

                                        message:errorTypepreferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *okAction = [UIAlertActionactionWithTitle:@"OK"style:UIAlertActionStyleCancelhandler:nil];

    [alertController addAction:okAction];

    [selfpresentViewController:alertController animated:YEScompletion:nil];

}


- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {

    

//    NSLog(@"update");

    self.currentPoint = [locationslastObject];

    

    NSString *latitudeString = [NSStringstringWithFormat:@"%g\u00B0",

                                self.currentPoint.coordinate.latitude];

    self.latitudeLabel.text = latitudeString;

    

    NSString *longitudeString = [NSStringstringWithFormat:@"%g\u00B0",

                                 self.currentPoint.coordinate.longitude];

    self.longitudeLabel.text = longitudeString;

    

    if (self.currentPoint.horizontalAccuracy < 0) {

        // invalid accuracy

        return;

    }

    

    if (self.currentPoint.horizontalAccuracy > 100 ||

        self.currentPoint.verticalAccuracy >50) {

        // accuracy radius is so large, we don't want to use it

        return;

    }

    

    if (self.destinationPoint != nil) {//若已经设定了目的地的经纬度,则计算当前地点与目的地之间的距离

    

        CLLocationDistance distance = [self.currentPoint

                                       distanceFromLocation:self.destinationPoint];

        

        NSString *distanceString = [NSStringstringWithFormat:@"%gm",

                                    distance];

        

        if(distance<500)//当距离目的地小于500米的时候就认为到达目的地

        {

//            [self.locationManager stopUpdatingLocation];

            self.distanceLabel.text =@"您已经到达目的地!";

        }

        else

        {

            self.distanceLabel.text = [NSStringstringWithFormat:@"距离目的地还有%@",distanceString];

        }

    }

}

@end



定位原理:

iOS设备都可以使用哪些方式进行定位?
最早期的iPhone只支持 手机基站定位, 之后通过iOS软件升级引入了 WIFI定位, 而从iPhone 3G开始, iPhone手机就通过内置GPS处理芯片, 支持 GPS卫星定位 (准确地说, 应该是AGPS, 即:辅助GPS). 从iPhone 4开始,GPS换用了精确度更高,耗电更少的,灵敏度更高的芯片,而从iPhone4s和new iPad 3G版开始,增加了对俄罗斯GLONASS卫星定位系统的支持。


定位模式有3种:
1、卫星定位
(1)GPS卫星定位:iPhone 3G/3GS/4/5,3G/4G版的iPad 支持
(2)GLONASS卫星定位:iPhone 4/5,3G/4G版的iPad 3/4/Mini 支持
2、手机基站定位
同GPS卫星定位,即iPhone 3G/3GS/4/5,3G/4G版的iPad 支持
3、WIFI定位
所有iOS设备,包括Mac电脑也支持。

手机基站定位:

原理:
每个手机基站都有一个标识符,iPhone或3G iPad可以搜集周围所有收到信号的基站和它们的标识符,通过联网发送到苹果云端服务器,再由服务器根据这些基站的的位置信息查询并计算出当前位置,然后返回给手机。因为基站信号辐射范围大,所以误差也大,在500米 ~ 几公里. 

特点:定位速度最快, 耗电最少,误差几百上千米.

iOS优化:
无网基站定位:
传统的基站定位需要连接云端服务器,产生网络流量,iOS 4对其进行了优化,可以在没有网络连接时支持无网定位,因为苹果预先已经将一些重要基站(几十公里选一个)提前存储在iOS系统中,在无网情况下,不用上网也能通过这些本地基站信息定位到用户位置,但这个误差范围更大,在10公里到50公里。
无网基站定位的前提是:您的手机能接受到内置在手机中的那些“重要基站”的信号,不一定是您手机所属运营商,只要能收到信号就可以了。

WIFI定位:

原理
和基站定位原理差不多, iOS设备(或者Mac电脑)通过无线网卡手机周围所有的WIFI热点(不需要连接上,只需要有信号就行),获得它们的MAC地址,然后到苹果云端服务器查询这个热点是否已经登记,登记的话它的位置是多少,最后通过计算(多个热点折中)得到当前位置并返回给用户。只要收到手机信号的地方都可以基站定位,所以室内室外一样。

特点:WIFI定位速度、耗电和精度都介于基站和GPS之间,精度大概在几十米。(注意,WIFI定位的支持范围没有基站定位广,但是苹果的云端服务器一直在不断增加新的热点信息,使得热点定位支持的地区越来越多)
 
iOS优化:
无网WIFI定位:
传统的WIFI定位需要网络,但是iOS对其进行了优化,可以实现无网WIFI定位。原理是iOS设备在有网络连接时,会大致定位出您的位置,并自动下载您所在地区周围(几个街区宽度或者更多)所有的WIFI热点的信息到本地。之后,当您在周围行走并WIFI定位的时候,即使没有网络,iOS照样可以利用之前下载的WIFI热点信息定位出您的位置。
这也是为什么有人号称WIFI无网可定位的原因,但注意:无网WIFI定位的前提是您在这个区域附近曾经成功上过网,如果初次到一个陌生的地方,是无法定位的哦。

关于自动下载的热点个数和范围,这个是苹果根据当地热点的密度动态决定的,当地热点很多时(如市中心),可能只下载几条街道范围的所有热点,当地热点密度很小时(例如海滨城市),可能会下载整个城市的所有热点。

GPS定位:

GPS的定位原理与GLONASS类似,均为卫星定位系统,只不过前者是美国建立的,后者是俄罗斯建立的。

原理
GPS美国军方搞的, 军民两用, 但仍然完全受军方控制(比如可以随时随地设置某个地区是否可以收到信号及其精度), 其原理就是:利用天上的卫星(24颗工作卫星和数颗备份星)不断地广播信号, 地面的GPS接收设备收到信号后, 通过分析多个卫星信号,就可以计算出地球坐标, GPS保证全球任何一个地方(98%)都可以同时收到至少4个卫星的信号, 从而可以准确确定您的经纬度以及海拔位置(三颗星只能获得经纬度,四颗星还可以获得海拔高度)。GPS定位精度可达10米以内(美军的精度可以达到一米以下), 不过这是美国军方控制的, 战争时期可能变的不稳定或者误报。 (我国也有自己的系统,北斗定位系统,覆盖亚洲范围,还在积极建设和推广中)

卫星定位必须要能收到卫星信号,因为卫星信号都是很微弱的,虽然iPhone 4开始提升了GPS硬件的灵敏度,但仍然需要在窗户旁,或者户外使用,才能确保卫星信号的强度和稳定性。

与基站定位和WIFI定位相比,GPS耗电最大,速度最慢,但是精度最高。
与纯粹的GPS定位不同,苹果采用的 A-GPS, 即辅助GPS。(比GPS更优,不过GPS也分芯片和性能的,不是说所有的AGPS比所有的GPS都好)

因为GPS定位中最耗时、最耗电的就是获取当前天上的卫星信息,哪些卫星可见、在什么位置、时钟是多少等等,这个过程可能花费数十秒甚至几分钟,而AGPS就是利用网络,首先将基站定位或者WIFI定位获得的大概位置发到远程服务器,由服务器进行查询和计算,得出这个位置下当前卫星信息,反馈给iOS设备,iOS设备就可以直接用这些信息来接受卫星信号,不用自己去扫描分析了。这样可以极大提高定位速度,将初次定位时间缩短到1~2秒完成。

A-GPS优点是定位快,缺点是需要网络,但也只是在初次定位时需要网络,因为一旦卫星信息返回,在有限时间和范围内,这些信息无须改变,之后的GPS定位就不再需要联网,都是直接用这些卫星参数接受信息了。

-------------------------------------------------------------------------------------------------------

在iOS设备上,上述定位方式会综合应用,一般地,可能先按照最快的“无网基站定位”返回一个位置,当有网络连接时,在用有网基站定位更新位置,然后,利用AGPS上网查询卫星星图,最后,在能收到GPS信号的情况下,转为使用GPS定位。

根据当前信号情况和网络环境,iOS可能在上述方式之间反复迭代,不一定一致特定步骤或者方式,而且随着iOS升级,定位顺序和规则可能改变。

----------------------------------------------------------------------------------------------------

常见问题:


1. 为什么我iPhone当前定位误差有几百或者上千米?
iPhone初始定位都是用基站或者无网基站定位,误差几百或几公里。之后,如果无法搜索到WIFI信号,或者无法搜索到卫星信号,就会一直是这个精度。
您可以打开WIFI功能(不用连上,只需要打开即可),或者到窗户边,或者户外以便收到卫星信号; 
解决方法: 多等一会儿,开启数据流量(定位之后即可关闭),或者到户外去。

2. 为什么我的位置总是变来变去?
iOS根据当前网络环境,会不断调整和修正定位方式,可能您所处地区基站和WIFI信号太复杂或者太微弱,比如一会儿连上这个基站,一会儿连上另一个基站,导致iOS计算位置的时候不稳定。
解决方法: 打开WIFI功能,开启数据流量(定位之后即可关闭),或者到户外去。

3. 无手机信号可以定位吗?无数据流量可以定位吗?
对于iPhone或者3G/4G版iPad
情况1:【没有手机信号,没有WIFI信号,没有上网】则定位只能在户外利用GPS进行,初次定位时间可能很长,可能需要数分钟,之后定位正常。
情况2:【没有手机信号, 有WIFI信号,没有上网】如果之前在周围上过网,下载了附近的热点,则利用无网WIFI定位可以找到位置,否则,和情况1一样。
情况3:【没有手机信号, 有WIFI信号,可以上网】利用WIFI定位找到位置,并且在定位时还会下载大量的周围很大一个区域的所有WIFI热点信息,用于今后无网WIFI定位。
情况4:【有手机信号, 没有WIFI信号,没有上网】如果能收到iOS内置的“重要基站”的信号,则使用这些基站进行无网基站定位,否则,无法定位。
情况5:【有手机信号, 没有WIFI信号,可以上网】使用基站定位联网查询进行定位,同时可能会更新本地“重要基站”信息。
.......
对于iPad WIFI版:
情况1:【没有WIFI信号,没有上网】无法定位
情况2:【有WIFI信号,没有上网】如果之前在周围上过网,则利用无网WIFI定位可以找到位置,否则,无法定位
情况3:【有WIFI信号,可以上网】利用WIFI定位,并且在定位时还会下载周围很大一个区域的所有WIFI热点信息,用于今后无网WIFI定位
1 0
原创粉丝点击