需要在Info.plist文件中设置一下,加入一个NSLocationWhenInUseUsageDescription(前台获取GPS定位),NSLocationAlwaysUsageDescription(前后台获取GPS定位),Value可以为空;
引头文件
#import
签协议
@interface ViewController ()
写俩懒加载, 待会会用到
- (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
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 * _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];
}