需要在Info.plist文件中設置一下,加入一個NSLocationWhenInUseUsageDescription(前臺獲取GPS定位),NSLocationAlwaysUsageDescription(前后臺獲取GPS定位),Value可以為空;
引頭文件
#import <CoreLocation/CoreLocation.h>
簽協議
@interface ViewController ()<CLLocationManagerDelegate>
寫倆懶加載, 待會會用到
- (CLGeocoder *)geocoder{
if (!_geocoder) {
_geocoder = [[CLGeocoder alloc] init];
}
return _geocoder;
}
- (CLLocationManager *)locationManager{
if (!_locationManager) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
return _locationManager;
}
接下來可以在 viewDidLoad 和 刷新定位按鈕響應事件 的地方調用下面方法, 開始定位, 最好別在viewWillAppear調用, 用戶關閉過一次權限她不想老被提醒
#pragma mark - 定位
- (void)beginLocate{
if ([CLLocationManager locationServicesEnabled]) {
/** 由于IOS8中定位的授權機制改變 需要進行手動授權
* 獲取授權認證,兩個方法:
* [self.locationManager requestWhenInUseAuthorization];
* [self.locationManager requestAlwaysAuthorization];
*/
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
// NSLog(@"requestWhenInUseAuthorization");
[self.locationManager requestWhenInUseAuthorization];
}
//開啟定位, 不斷調用其代理方法
[self.locationManager startUpdatingLocation];
// NSLog(@"start gps");
}
if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied){
NSLog(@"定位權限被關閉");
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"抱歉" message:@"您尚未開啟定位權限" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil];
UIAlertAction *actionOk = [UIAlertAction actionWithTitle:@"去設置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self jumpToSetting];
}];
[alertController addAction:actionCancel];
[alertController addAction:actionOk];
[self presentViewController:alertController animated:YES completion:nil];
}
}
#pragma mark - 去系統設置開啟權限
- (void)jumpToSetting{
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
//info plist中URL type中添加一個URL Schemes添加一個prefs值
if([[UIApplication sharedApplication] canOpenURL:url]){
//跳轉到定位
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=LOCATION_SERVICES"]];
}
}
這是定位的代理方法
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
if(!_isLocationed){
//1.獲取最新的一次位置信息
CLLocation *location = [locations lastObject];
CLLocationCoordinate2D coordinate = location.coordinate;
//NSLog(@"經度:%f, 緯度:%f", coordinate.longitude, coordinate.latitude);
//逆地理編碼得到當前定位城市
[self reGeoCoderLocation:coordinate];
}else{
//2.停止定位
[self.locationManager stopUpdatingLocation];
}
}
#pragma mark - 逆地理編碼
- (void)reGeoCoderLocation:(CLLocationCoordinate2D)coordinate{
//根據經緯度反向地理編譯出地址信息
CLLocation *location = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude];
[self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (placemarks.count > 0) {
CLPlacemark *placemark = placemarks.firstObject;
//placemark.name位置全名
//
//placemark.thoroughfare街道
//
//placemark.subThoroughfare子街道
//
// placemark.locality市
//
//placemark.subLocality區
//
//placemark.country國家
//NSLog(@"全稱:%@, 市:%@, 區:%@, 街道:%@, 子街道:%@", placemark.name, placemark.locality, placemark.subLocality, placemark.thoroughfare, placemark.subThoroughfare);
//NSString *city = placemark.locality;
if (!city) {
//四大直轄市的城市信息無法通過locality獲得,只能通過獲取省份的方法來獲得(如果city為空,則可知為直轄市)
city = placemark.administrativeArea;
}
//獲取具體位置
NSString *strOfAccurate = placemark.name;
NSString *strOfCity = placemark.locality;
NSString *strOfThroughfare = placemark.thoroughfare;
if (!strOfCity || !strOfAccurate || !strOfThroughfare) {
_isLocationed = NO;
[self.locationManager startUpdatingLocation];
}else{
_isLocationed = YES;
_locationView.labelOfLocation.text = [NSString stringWithFormat:@"當前: %@%@", strOfCity, strOfAccurate];
}
}
else if (error == nil && placemarks.count == 0){
NSLog(@"定位無返回結果");
}
else if(error != nil){
NSLog(@"location error: %@", error);
}
}];
}
#pragma mark - 試圖將要消失
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
//定位停止
[self.locationManager stopUpdatingLocation];
}
以下這個協議方法也可以
//代理方法:獲取地理位置變化的起始點和終點,didUpdateToLocation:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
//將經度顯示到label上
self.longitude.text = [NSString stringWithFormat:@"%lf", newLocation.coordinate.longitude];
//將緯度顯示到label上
self.latitude.text = [NSString stringWithFormat:@"%lf", newLocation.coordinate.latitude];
// 獲取當前所在的城市名
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//根據經緯度反向地理編譯出地址信息
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *array, NSError *error){
if (array.count > 0){
CLPlacemark *placemark = [array objectAtIndex:0];
//將獲得的所有信息顯示到label上
self.location.text = placemark.name;
//獲取城市
NSString *city = placemark.locality;
if (!city) {
//四大直轄市的城市信息無法通過locality獲得,只能通過獲取省份的方法來獲得(如果city為空,則可知為直轄市)
city = placemark.administrativeArea;
}
NSLog(@"city = %@", city);
_cityLable.text = city;
// [_cityButton setTitle:city forState:UIControlStateNormal];
}
else if (error == nil && [array count] == 0)
{
NSLog(@"No results were returned.");
}
else if (error != nil)
{
NSLog(@"An error occurred = %@", error);
}
}];
//系統會一直更新數據,直到選擇停止更新,因為我們只需要獲得一次經緯度即可,所以獲取之后就停止更新
[manager stopUpdatingLocation];
}