最近发现之前写的一个定位城市的程序突然不工作了,查询了一下才知道IOS8下做了新的修改。
先来看看我们怎么去定位我们所在城市吧。
.h文件
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <CoreLocation/CLLocationManagerDelegate.h>
#import <MapKit/MapKit.h>
@interface LocationViewController : UIViewController<MKMapViewDelegate,CLLocationManagerDelegate,UIAlertViewDelegate>
{
MKMapView *map;
CLLocationManager *locationManager;
}
@property (retain,nonatomic) CLLocationManager *locationManager;
@property (retain,nonatomic) CLGeocoder *currentCityGeocoder;
@end
为了增加效果我还加入了一个map,显示定位的过程。当然你只是要最后的城市,不加map也没有什么关系。
.m文件
- (void)viewDidLoad {
currentCityGeocoder = [[CLGeocoder alloc]init]; //1
locationManager = [[CLLocationManager alloc]init]; //2
locationManager.delegate = self; //3
locationManager.distanceFilter = 1000.0f; //4
locationManager.desiredAccuracy = kCLLocationAccuracyBest; //5
self.getTheCity = NO;
if (nil == locationManager)
{
locationManager = [[CLLocationManager alloc] init];
}
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)//6
[locationManager requestWhenInUseAuthorization];
[super viewDidLoad];
}
1、对CLGeocoder对象进行初始化2、对CLLocationManager对象进行初始化
3、设置定位服务委托为self
4、设置距离过滤器distanceFilter的属性,他定义设备移动更新位置信息的最小距离,简单来说,你移动超过1000m以后位置信息将会更新
5、desiredAccuracy是重要的精度属性,他包括6个常量:
kCLLocationAccuracyNearestTenMeters。精度10米
kCLLocationAccuracyHundredMeters。精度100 米
kCLLocationAccuracyKilometer。精度1000 米
kCLLocationAccuracyThreeKilometers。精度3000米
kCLLocationAccuracyBest。设备使用电池供电时候最高的精度
最高的精度;kCLLocationAccuracyBestForNavigation。导航情况下最高精度,一般要有外接电源时才使用
6、我们会发现以前写得城市定位程序不工作了,查询GPS授权情况会发现:CLAuthorizationStatus.NotDetermined(授权状态未定)
我们在viewDidLoad里加入一个判断:
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[locationManager requestWhenInUseAuthorization];
同时在Info.plist文件中加入两个字段(可以缺省),目的是为了自定义提醒用户授权使用地理定位功能的提示语
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
如图:
然后我们需要对map的基本属性进行设置
-(void)viewWillAppear:(BOOL)animated{
map = [[MKMapView alloc] initWithFrame:[self.view bounds]];
map.showsUserLocation = YES;
map.mapType = MKMapTypeStandard;
[self.view addSubview:map];
[self performSelector:@selector(showCurrentCityInAlertView) withObject:nil afterDelay:2.0f];
[locationManager startUpdatingLocation]; //7
}
[locationManagerstartUpdatingLocation]开始定位服务,根据设定条件按不断回调新的位置信息。所以我们在开启与关闭定位服务的时候要慎重,以免出错。一般在ViewWillAppear中开启,在ViewWillDisappear中关闭服务[locationManager stopUpdatingLocation]
-(void)viewWillDisappear:(BOOL)animated{
[locationManager stopUpdatingLocation];
}
最后我们要开始获取城市啦
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
currentCityGeocoder = [[CLGeocoder alloc]init];
[currentCityGeocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *array, NSError *error)
{
if (array.count > 0)
{
CLPlacemark *placemark = [array objectAtIndex:0];
NSString *city = placemark.locality;
if (!city) {
city = placemark.administrativeArea;
}
}
else if (error == nil && [array count] == 0)
{
NSLog(@"No results were returned.");
}
else if (error != nil)
{
NSLog(@"An error occurred = %@", error);
}
}];
CLLocationCoordinate2D coords = CLLocationCoordinate2DMake(newLocation.coordinate.latitude,newLocation.coordinate.longitude);
float zoomLevel = 0.07;
MKCoordinateRegion region = MKCoordinateRegionMake(coords, MKCoordinateSpanMake(zoomLevel, zoomLevel));
[map setRegion:[map regionThatFits:region] animated:YES];
}
我们用CLPlacemark来获取地理位置的详细信息,如国家、省份、城市甚至是街道名称。
同时我们还会加入一个判断语句,因为直辖市的城市信息无法通过placemark.locality获得,只能通过获取省份的方法来获得,所以当city为nil时,我们就用placemark.administrativeArea来获取城市。而 newLocation.coordinate.latitude 与 newLocation.coordinate.longitude 就是当前位置的经纬度。
MKCoordinateRegion用来设置坐标显示范围
MKCoordinateRegion region =MKCoordinateRegionMake(coords, MKCoordinateSpanMake(zoomLevel, zoomLevel))
coords就是以当前经纬度所在位置为中心, 上下 zoomLevel的 区域
[mapsetRegion:[mapregionThatFits:region] animated:YES]表示最终显示该区域
现在基本功能已经实现了,但还要考虑到获取信息失败的情况:
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
// Failed to receive user's location
NSString *errorMsg = nil;
if ([error code] == kCLErrorDenied) {
errorMsg = @"访问被拒绝";
}
if ([error code] == kCLErrorLocationUnknown) {
errorMsg = @"获取地理位置失败";
}
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Location"
message:errorMsg delegate:self cancelButtonTitle:@"Ok"otherButtonTitles:nil, nil];
[alertView show];
}