首页 > 代码库 > 适配ios8.0/7.0定位

适配ios8.0/7.0定位

现象

假如你用做ios8之前的定位去在ios8.0的机子上跑的话,你会发现 诶?怎么定位功能不能用了,右上角那个定位的小图标不出来。这时你应该去了设置里面看看隐私——定位,看到没有开启,然后改成始终,然后程序重新跑过,然后你又发现还是不能用。。。于是你又去设置那里看看,靠 发现改成的始终怎么给取消了。。(其实这就是我。。)

原因

在以前的IOS版本中当开始使用定位服务时会自动弹出询问授权的对话框,而现在IOS8需要手动调用locationManager requestAlwaysAuthorization手动申请授权,来获取定位权限。
苹果在ios8.0之后给了我们两个东西

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

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

这两个东西呢 就是用来手动获取定位权限的。你可以分别设置 注意看,当你使用上面的 第一次会提示窗口 当你使用可不可以获取你位置,下面这个则会弹出当你未使用可不可以,当然 下面这个更强大。。。

苹果官方是这么说的 大家去看API吧。。

在ios8.0中的方法

假如你用的是百度定位 或者任何第三方定位 都没关系,因为现在的方法仅仅是提供一个把定位功能开启的作用,我们要用到苹果自己的定位参数

        _locationManager = [[CLLocationManager alloc] init];//创建位置管理器
        _locationManager.delegate = (id)self;
        _locationManager.desiredAccuracy=kCLLocationAccuracyBest;
        _locationManager.distanceFilter=100.0f;
        //定位服务是否可用
        _enable=[CLLocationManager locationServicesEnabled];
        //是否具有定位权限
        _status=[CLLocationManager authorizationStatus];
        if(!_enable || _status<3){
            //请求权限
            [_locationManager requestAlwaysAuthorization];
//            [_locationManager requestWhenInUseAuthorization];
        }

记住 locationManager必须是全局变量,不可为局部变量,当为局部变量是手动定位提示AlertView会一闪而过! 我刚开始就一直出现就没了,点都来不及点,所以这样肯定不行的,后面自己试着试着就可以了,原来是无意之中设为全局就行了。


在info.plist里面添加一个key: NSLocationAlwaysUsageDescription,value 好像是可以随便设的。。

或者 NSLocationWhenInUseUsageDescription  BOOL 类型 数值为YES 或者好像是随便设的。。。


这样之后  系统就会提示是否开启了。 当然,上述方法是放在AppDelegate里面的,程序第一次刚启动,就先告诉用户。

但是,假如我们在用到的时候才提醒呢,这时假如你也这样写,在询问之后 

       [_userLocationstartUserLocationService];

这样会发生什么呢,这样会导致第一次显示不出来,因为询问的时候 这个百度的开启定位功能已经执行了,所以第一次不行,你第二次进来才显示正确。

这时就要用到

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status;

这个就是状态改变的时候会做的,但是我发现,刚开始 点了之后会执行一次,当你定位又会执行一次,至于为什么 我也没去多想,总之 我是在里面这样判断

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    
    _enable=[CLLocationManager locationServicesEnabled];
    _status=[CLLocationManager authorizationStatus];
    if(!_enable || _status<3){
        
    }else{
        [_mapView viewWillAppear];
        [_userLocation startUserLocationService];
        //    _mapView.showsUserLocation = NO;//先关闭显示的定位图层
        _mapView.userTrackingMode = BMKUserTrackingModeNone;//设置定位的状态
        _mapView.showsUserLocation = YES;//显示定位图层
        
        _mapView.delegate = self;
        _geocodesearch.delegate = self;
        _userLocation.delegate = self;
        _walkingRoutePlanOption.delegate = self;
    }
}
这样就搞定了 此时,把要定位的都放这里。但是 你这样写完之后 在ios7上跑就会报错了,因为你用了ios8的方法,此时我们就要适配了。。

适配ios8.0/7.0定位

#define IOSVersion                          [[[UIDevice currentDevice] systemVersion] floatValue]

#define IsIOS7Later                         !(IOSVersion < 7.0)

#define IsIOS8Later                         !(IOSVersion < 8.0)


直接贴上代码

在AppDelegate中可以这么写

    if (IsIOS8Later) {
        _locationManager = [[CLLocationManager alloc] init];//创建位置管理器
        _locationManager.delegate = (id)self;
        _locationManager.desiredAccuracy=kCLLocationAccuracyBest;
        _locationManager.distanceFilter=100.0f;
        //定位服务是否可用
        _enable=[CLLocationManager locationServicesEnabled];
        //是否具有定位权限
        _status=[CLLocationManager authorizationStatus];
        if(!_enable || _status<3){
            //请求权限
            [_locationManager requestAlwaysAuthorization];
//            [_locationManager requestWhenInUseAuthorization];
        }
    }
    return YES;

假如你是在控制器中的话

- (void)viewDidLoad

   if(IsIOS8Later){
        _locationManager = [[CLLocationManager alloc] init];//创建位置管理器
        _locationManager.delegate = (id)self;
        _locationManager.desiredAccuracy=kCLLocationAccuracyBest;
        _locationManager.distanceFilter=100.0f;
        //定位服务是否可用
        _enable=[CLLocationManager locationServicesEnabled];
        //是否具有定位权限
        _status=[CLLocationManager authorizationStatus];
        if(!_enable || _status<3){
            //请求权限
            [_locationManager requestAlwaysAuthorization];
            [_locationManager requestWhenInUseAuthorization];
        }
    }else{
        [_userLocation startUserLocationService];
        _mapView.showsUserLocation = NO;//先关闭显示的定位图层
        _mapView.userTrackingMode = BMKUserTrackingModeNone;//设置定位的状态
        _mapView.showsUserLocation = YES;//显示定位图层
        
    }

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    
    _enable=[CLLocationManager locationServicesEnabled];
    _status=[CLLocationManager authorizationStatus];
    if(!_enable || _status<3){
        
    }else{
        [_mapView viewWillAppear];
        [_userLocation startUserLocationService];
        //    _mapView.showsUserLocation = NO;//先关闭显示的定位图层
        _mapView.userTrackingMode = BMKUserTrackingModeNone;//设置定位的状态
        _mapView.showsUserLocation = YES;//显示定位图层
        
        _mapView.delegate = self;
        _geocodesearch.delegate = self;
        _userLocation.delegate = self;
        _walkingRoutePlanOption.delegate = self;
    }
}

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    if(IsIOS8Later){
        if(!_enable || _status<3){
            //请求权限
            [_locationManager requestAlwaysAuthorization];
            [_locationManager requestWhenInUseAuthorization];
        }
    }else{
        [_mapView viewWillAppear];
        [_userLocation startUserLocationService];
        _mapView.showsUserLocation = NO;//先关闭显示的定位图层
        _mapView.userTrackingMode = BMKUserTrackingModeNone;//设置定位的状态
        _mapView.showsUserLocation = YES;//显示定位图层
        
        _mapView.delegate = self;
        _geocodesearch.delegate = self;
        _userLocation.delegate = self;
        _walkingRoutePlanOption.delegate = self;
    }
}

当然 可以继续优化,定位部分是我刚刚学ios的时候做的,写的不太好,就不多说了,大体思路就是这样

适配ios8.0/7.0定位