標籤:ios8 定位 適配
現象假如你用做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定位