现象
原因
- (void)requestWhenInUseAuthorization __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0);
- (void)requestAlwaysAuthorization __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0);
这两个东西呢 就是用来手动获取定位权限的。你可以分别设置 注意看,当你使用上面的 第一次会提示窗口 当你使用可不可以获取你位置,下面这个则会弹出当你未使用可不可以,当然 下面这个更强大。。。在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的时候做的,写的不太好,就不多说了,大体思路就是这样。
==================11月19日更新==========================
*需要在info.plist文件中添加(以下二选一,两个都添加默认使用NSLocationWhenInUseUsageDescription):
*NSLocationWhenInUseUsageDescription 允许在前台使用时获取GPS的描述
*NSLocationAlwaysUsageDescription 允许永远可获取GPS的描述
-(void)viewWillDisappear:(BOOL)animated {
[_mapView viewWillDisappear];
_mapView.delegate = nil; // 不用时,置nil
_locService.delegate = nil;
}
无需调用
[
super
viewWillDisAppear
:animated];
[_userLocation stopUserLocationService];
[_userLocation starUserLocationService];
实例化百度地图相关参数。
这3点非常重要,否则你会发现你的定位莫名其妙就不能用了。
3、19号前的 判断是否是ios8的方法已经不需要了,现在可以直接和ios7一样写方法了。只是plist文件要写东西,记住。
还有就是要提醒大家一点。百度地图的.a文件是分为两种的。一个是模拟器的.a,一个真机.a,你可以选择合并或者跑哪个放哪个。