iOS 定位功能的实现

作者: stillwalking | 来源:发表于2015-05-11 22:09 被阅读45221次
    1. 导入框架

       Xcode中添加“CoreLocation.framework”  
      
    2. 导入主头文件

       #import <CoreLocation/CoreLocation.h>
      
    3. 声明管理器和代理

       @interface ViewController ()<CLLocationManagerDelegate>
       @property (nonatomic, strong) CLLocationManager* locationManager;
       @end  
      
    4. 初始化管理器

       self.locationManager = [[CLLocationManager alloc] init];
       self.locationManager.delegate = self;
       self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
      
    5. 开启定位服务,需要定位时调用findMe方法:

       - (void)findMe
       {
           /** 由于IOS8中定位的授权机制改变 需要进行手动授权
            * 获取授权认证,两个方法:
            * [self.locationManager requestWhenInUseAuthorization];
            * [self.locationManager requestAlwaysAuthorization];
            */
           if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
               NSLog(@"requestAlwaysAuthorization");
               [self.locationManager requestAlwaysAuthorization];
           }
       
           //开始定位,不断调用其代理方法
           [self.locationManager startUpdatingLocation];
           NSLog(@"start gps");
       }
      
    6. 代理设置

       - (void)locationManager:(CLLocationManager *)manager
            didUpdateLocations:(NSArray *)locations
       {
           // 1.获取用户位置的对象
           CLLocation *location = [locations lastObject];
           CLLocationCoordinate2D coordinate = location.coordinate;
           NSLog(@"纬度:%f 经度:%f", coordinate.latitude, coordinate.longitude);
           
           // 2.停止定位
           [manager stopUpdatingLocation];
       }
       
       - (void)locationManager:(CLLocationManager *)manager
              didFailWithError:(NSError *)error
       {
           if (error.code == kCLErrorDenied) {
               // 提示用户出错原因,可按住Option键点击 KCLErrorDenied的查看更多出错信息,可打印error.code值查找原因所在
           }
       }
      

    注意事项

    1. iOS8中定位服务的变化:CLLocationManager协议方法不响应,无法回掉GPS方法,不出现获取权限提示,解决方法如下,详见1 详见2

       如果需要仅在前台定位,你在调用startUpdatingLocation 前需要调用requestWhenInUseAuthorization(见设置步骤6)  
       
       如果需要在前后台定位,你在调用startUpdatingLocation 前需要调用requestAlwaysAuthorization  
       
       在plist文件中添加NSLocationWhenInUseUsageDescription或(与)NSLocationAlwaysUsageDescription字段:  
       找到info.plist文件->右击->Open As->Source Code->在尾部的</dict>标签之前添加以下一个或两个:  
       <key>NSLocationWhenInUseUsageDescription</key><string>需要定位</string>  
       <key>NSLocationAlwaysUsageDescription</key><string>需要定位</string>  
      
    2. 用户隐私的保护

       从iOS 6开始,苹果在保护用户隐私方面做了很大的加强,以下操作都必须经过用户批准授权:要想获得用户的位置,想访问用户的通讯录、日历、相机、相册等;当想访问用户的隐私信息时,系统会自动弹出一个对话框让用户授权。
       
       可以在Info.plist中设置NSLocationUsageDescription说明定位的目的(Privacy - Location Usage Description)
       
       从iOS 8开始,用户定位分两种情况  
       总是使用用户位置:NSLocationAlwaysUsageDescription  
       使用应用时定位:NSLocationWhenInUseDescription  
       当想访问用户的隐私信息时,系统会自动弹出一个对话框让用户授权
       
       /**
        *打开定位服务
        *需要在info.plist文件中添加(以下二选一,两个都添加默认使用NSLocationWhenInUseUsageDescription):
        *NSLocationWhenInUseUsageDescription 允许在前台使用时获取GPS的描述
        *NSLocationAlwaysUsageDescription 允许永远可获取GPS的描述
      
    3. 获取当前软件的定位服务状态

       if ([CLLocationManager locationServicesEnabled]  //确定用户的位置服务启用  
       &&[CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied)  
       //位置服务是在设置中禁用  
           {  
           
           }
      
    4. 代码:调用startLocation方法即可

        #pragma mark Location and Delegate
        - (void)startLocation
        {
            self.locationManager = [[CLLocationManager alloc] init];
            self.locationManager.delegate = self;
            self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
            
            /** 由于IOS8中定位的授权机制改变 需要进行手动授权
             * 获取授权认证,两个方法:
             * [self.locationManager requestWhenInUseAuthorization];
             * [self.locationManager requestAlwaysAuthorization];
             */
            if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
                NSLog(@"requestWhenInUseAuthorization");
                //        [self.locationManager requestWhenInUseAuthorization];
                [self.locationManager requestAlwaysAuthorization];
            }
            
            
            //开始定位,不断调用其代理方法
            [self.locationManager startUpdatingLocation];
            NSLog(@"start gps");
        }
        
        - (void)locationManager:(CLLocationManager *)manager
             didUpdateLocations:(NSArray *)locations
        {
            // 1.获取用户位置的对象
            CLLocation *location = [locations lastObject];
            CLLocationCoordinate2D coordinate = location.coordinate;
            NSLog(@"纬度:%f 经度:%f", coordinate.latitude, coordinate.longitude);
            
            self.longitute = [NSNumber numberWithDouble:coordinate.longitude];
            self.latitude = [NSNumber numberWithDouble:coordinate.latitude];
            
            // 2.停止定位
            [manager stopUpdatingLocation];
        }
        
        - (void)locationManager:(CLLocationManager *)manager
               didFailWithError:(NSError *)error
        {
            if (error.code == kCLErrorDenied) {
                // 提示用户出错原因,可按住Option键点击 KCLErrorDenied的查看更多出错信息,可打印error.code值查找原因所在
            }
        }

    相关文章

      网友评论

      • 翎風:问一下,内嵌的H5获取实时定位,初始第一次打开授权的时候,会弹出 说 var/containers/Bundle/xxx/xxxx/xxxx/index.html Would Like To Use Your Current Location
        我怎么改为:允许“app名字”在您使用该应用时访问您的位置吗?
        主要是想把显示h5 路径的这段处理掉,不友好。试过很多方式,都不行。
      • 68f63b315167:在模拟器上时打印一次经纬度,在真机上打印两次或两次以上经纬度,怎么解决这个问题
      • 梁森的简书:使用定位功能需要开启location updates设置吗? 还需要进行其他的文件中的设置吗?如plist文件中的设置。 我的代码已经写好了并且能获取位置
        68f63b315167:在模拟器上时打印一次经纬度,在真机上打印两次或两次以上经纬度,怎么解决这个问题
        stillwalking:@阳光黑 那个是 APP 在后台需要更新定位时用的,不是必须,看是否有后台定位的需求。
      • 8e8977ba5029:当第一次弹出权限访问是,用户拒绝了,以后调用[self.locationManager requestWhenInUseAuthorization]; 这个方法就不会再弹起了,大神 可有解决方案啊
      • 呵呵哈哈嘿嘿:你好,为什么我在定位的时候,定位已经成功,获取到了经纬度,但是调用反编码方法
        - (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler的时候经常没有反应,获取不到对应的城市名
        呵呵哈哈嘿嘿:@stillwalking 会有这个输出
        Geocode error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x17064e9d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://dispatcher.is.autonavi.com/dispatcher, NSErrorFailingURLKey=https://dispatcher.is.autonavi.com/dispatcher, _kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4, NSLocalizedDescription=The request timed out.}
        呵呵哈哈嘿嘿:@stillwalking 没有,一直没有走到回调那儿,有时候得等好长时间
        stillwalking:@呵呵哈哈嘿嘿 这个方法收到消息了吗,能看到什么错误信息吗
      • astring:大神,如果选择的是使用期间退到后台时app上面有蓝条怎么办?
      • 乔_帮主:两个都添加默认使用NSLocationWhenInUseUsageDescription???两个添加完后怎么默认是显示勾选的是始终??
        stillwalking:太久了,都不知您说的是哪里的勾选?
      • 7282c709fcfc:请问,无网络可以进行GPS定位不?虚心求教。
        stillwalking:自己试一下。
      • Laughingg: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {

        }

        这个代码看着有点多余, locationManager 一定是实现了requestAlwaysAuthorization 方法的。 respondsToSelector 这样的判断基本只会用在判断代码的可选方法。
        stillwalking:@徐七的生活 是的,当时考虑到版本兼容
        acf4b9a1a804:他这是以前有ios7的时候,目前基本没啥用了 毕竟ios7版本的基本不用考虑了
      • 杏仁丶:您好,我最近在做经纬度获取相关的项目,想问下iOS有没有除了这种的其他定位方式,最好不需要用户点击授权的;主要是客户提的需求,想在不用用户授权的情况下用某种方式获取,通过网络请求时,服务器端根据IP能获取到较精确的经纬度吗
        Laughingg:@杏仁丶 不可能, 除非apple 放弃对用户隐私的保护。 那和安卓机有什么区别。
        站在测试的角度说,弹一个框出来。 对用户是有一定影响。 影响是什么呢? 用户看到的第一反应, 丫的, 这傻叉 app 获取的的隐私。
        杏仁丶:@Laughingg 嗯嗯,明白你说的意思,我表述的时候脑子有些短路了,根据IP只能说得到一个地址,经纬度是获取不到的;其实我想问的是有没有可能在不提示用户打开定位的情况下获取到用户的经纬度?之前去一个招标的时候,一个测试问我,嫌弃苹果提示用户打开定位会体验不好。。。。
        Laughingg:怎么可能,先说说是定位是怎么来的。 定位是通过 GPS 来实现的。 动态计算经纬度。你告诉我服务器那里来的经纬度。
      • wrlynxayy:你好 像这样写 有没有测试过 系统服务中 --- 时间与地点的消耗呢 我像楼主一样这样写 时间与地点项 耗流量非常严重 不知道楼主会不会呢?
        devileatapple:@wrlynxayy 我不是楼主。看你是否要精确定位了。我没什么了解,定位精度我取的是公里级的。所以定位还是挺快的。
        wrlynxayy:@devileatapple 我已经是kCLLocationAccuracyNearestTenMeters了 或者用什么方式进行定位可以使 时间与地点 减少消耗呢?楼主是否有了解过呢?
        devileatapple:精确定位的缘故。kCLLocationAccuracyBest
      • 7c1702fdd5d6:你好,我用地理反编码的时候,一直报错 Error Domain=kCLErrorDomain Code=2 "(null)"
        [geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (!error) {
        NSLog(@"sucesss");
        }else{
        NSLog(@"%@",error);
        }
        falc0n:那是你模拟器的原因,

      本文标题:iOS 定位功能的实现

      本文链接:https://www.haomeiwen.com/subject/djdfqttx.html