最近发现之前写的一个定位城市的程序突然不工作了,查询了一下才知道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

如图:

固定定位ios兼容_Object C

  

  然后我们需要对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];
}

(实际效果是能够看到地图信息,在截图的时候没有等map信息加载完,所以看不到地图信息)