CoreLocation定位

 1 CoreLocation的基礎使用

1>iOS7

    1.建立CoreLocation的管理者。CoreLocation要強引用git

    2.實現CLLocationManagerDelegate代理。數組

    3.開始或中止代理
app

#import <CoreLocation/CoreLocation.h>
@interface ViewController () <CLLocationManagerDelegate>
@property (nonatomic, strong)CLLocationManager *mrg;
@end
@implementation ViewController

-(CLLocationManager *)mrg
{
    if (_mrg == nil) {
        //1,建立CoreLocation的管理者
        self.mrg = [[CLLocationManager alloc] init];
        
    }
    return _mrg;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //2,成爲CoreLocation的代理
    self.mrg.delegate = self;
    
    //3,開始定位
    [self.mrg startUpdatingLocation];
    
}

#pragma mark - CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
     NSLog(@"%s",__func__);
    
    //打印位置信息
        /*
     location.coordinate; 座標, 包含經緯度
     location.altitude; 設備海拔高度 單位是米
     location.course; 設置前進方向 0表示北 90東 180南 270西
     location.horizontalAccuracy; 水平精準度
     location.verticalAccuracy; 垂直精準度
     location.timestamp; 定位信息返回的時間
     location.speed; 設備移動速度 單位是米/秒, 適用於行車速度而不太適用於不行
     */
    CLLocation *location = [locations lastObject];
    NSLog(@"%f,%f",location.coordinate.latitude,location.coordinate.longitude);
    
    
    //  獲取到位置信息以後就會調用(調用頻率很是高).若是隻須要獲取一次, 就要在這裏設置中止
    //  [self.mgr stopUpdatingLocation];
}
2>iOS8

          iOS7只要開始定位, 系統就會自動要求用戶對你的應用程序受權. 可是從iOS8開始, 想要定位必須先"本身""主動"要求用戶受權.在iOS8中不單單要主動請求受權, 並且必須再info.plist文件中配置一項屬性才能彈出受權窗口,value值能夠隨意寫.eg:iOS7也能夠添加,但不強制。框架

            Privacy - Location Usage Description(iOS7)ide

            NSLocationWhenInUseDescription,容許在前臺獲取GPS的描述動畫

            NSLocationAlwaysUsageDescription,容許在後臺獲取GPS的描述編碼

    if([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0)
    {
        NSLog(@"是iOS8");
        // 主動要求用戶對咱們的程序受權, 受權狀態改變就會通知代理
        [self.mgr requestAlwaysAuthorization];     // 請求前臺和後臺定位權限
//      [self.mgr requestWhenInUseAuthorization];  // 請求前臺定位權限
    }
    
 //iOS8中須要額外添加在個代理方法
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    /*
     用戶從未選擇過權限
     kCLAuthorizationStatusNotDetermined
     沒法使用定位服務,該狀態用戶沒法改變
     kCLAuthorizationStatusRestricted
     用戶拒絕該應用使用定位服務,或是定位服務總開關處於關閉狀態
     kCLAuthorizationStatusDenied
     已經受權(廢棄)
     kCLAuthorizationStatusAuthorized
     用戶容許該程序不管什麼時候均可以使用地理信息
     kCLAuthorizationStatusAuthorizedAlways
     用戶贊成程序在可見時使用地理位置
     kCLAuthorizationStatusAuthorizedWhenInUse
     */  
    if (status == kCLAuthorizationStatusNotDetermined) {
        NSLog(@"等待用戶受權");
    }else if (status == kCLAuthorizationStatusAuthorizedAlways ||
              status == kCLAuthorizationStatusAuthorizedWhenInUse)
        
    {
        NSLog(@"受權成功");
        // 開始定位
        [self.mgr startUpdatingLocation];
        
    }else
    {
        NSLog(@"受權失敗");
    }
}


2 CoreLocation的經常使用屬性

    1.// 設置多久獲取一次(單位是米,超出多米就開始調用)
    self.mgr.distanceFilter = 500;
    
    2.// 設置獲取位置的精確度
    /*
      kCLLocationAccuracyBestForNavigation 最佳導航
      kCLLocationAccuracyBest;  最精準
      kCLLocationAccuracyNearestTenMeters;  10米
      kCLLocationAccuracyHundredMeters;  百米
      kCLLocationAccuracyKilometer;  公里
      kCLLocationAccuracyThreeKilometers;  3公里
     */
    self.mgr.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;


CoreLocation的經常使用功能 

1>導航
// 上一次的位置
@property (nonatomic, strong) CLLocation *previousLocation;
// 總路程
@property (nonatomic, assign) CLLocationDistance  sumDistance;
// 總時間
@property (nonatomic, assign) NSTimeInterval  sumTime;

#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    
    // 獲取當前的位置
    CLLocation *newLocation = [locations lastObject];
    
    if (self.previousLocation != nil) {
        // 計算兩次的距離(單位時米) 
        CLLocationDistance distance = [newLocation distanceFromLocation:self.previousLocation];
        // 計算兩次之間的時間(單位只秒) timestamp 當前獲取到爲止信息的時間
        NSTimeInterval dTime = [newLocation.timestamp timeIntervalSinceDate:self.previousLocation.timestamp];
        // 計算速度(米/秒)
        CGFloat speed = distance / dTime;
        
        // 累加時間
        self.sumTime += dTime;
        
        // 累加距離
        self.sumDistance += distance;
        
        //  計算平均速度
        CGFloat avgSpeed = self.sumDistance / self.sumTime;
        
        NSLog(@"距離%f 時間%f 速度%f 平均速度%f 總路程 %f 總時間 %f", distance, dTime, speed, avgSpeed, self.sumDistance, self.sumTime);
    }
    
    // 紀錄上一次的位置
    self.previousLocation = newLocation;
    
}
2>指南針
    // 1.添加指南針圖片
    UIImageView *iv = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"bg_compasspointer"]];
    iv.center = CGPointMake(self.view.center.x, self.view.center.y);
    [self.view addSubview:iv];
    self.compasspointer = iv;

#pragma mark - CLLocationManagerDelegate
// 當獲取到用戶方向時就會調用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
    /*
     magneticHeading 設備與磁北的相對角度;trueHeading 設置與真北的相對角度
     必須和定位一塊兒使用, 通常使用磁北
     
     順時針 正
     逆時針 負數
     */
    
    // 1.將獲取到的角度轉爲弧度 = (角度 * π) / 180;
    CGFloat angle = newHeading.magneticHeading * M_PI / 180;
    // 2.旋轉圖片 效果很差,建議使用核心動畫
    self.compasspointer.transform = CGAffineTransformMakeRotation(-angle);
}
3>區域監聽
- (void)viewDidLoad {
    [super viewDidLoad];
    self.mgr.delegate = self;
    
    // 注意:若是是iOS8, 想進行區域檢測, 必須本身主動請求獲取用戶隱私的權限.像CoreLocation的iOS8使用同樣,須要在info添加權限,如NSLocationAlwaysUsageDescription
    if  ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0 )
    {
        [self.mgr requestAlwaysAuthorization];
    }
   
    // 開始檢測用戶所在的區域
     //1.建立區域
    /*CLRegion 有兩個子類是專門用於指定區域的
    一個能夠指定藍牙的範圍CLBeaconRegion/ 一個是能夠指定圓形的範圍CLCircularRegion
    */
    //建立圓形區域, 指定區域中心點的經緯度, 以及半徑、標識
    CLLocationCoordinate2D center = CLLocationCoordinate2DMake(40.058501, 116.304171);  
    CLCircularRegion *circular = [[CLCircularRegion alloc] initWithCenter:center radius:500 identifier:@"軟件園"];  
    
    //2.開始監聽
    [self.mgr startMonitoringForRegion:circular];
 
}

#pragma mark - CLLocationManagerDelegate
// 進入監聽區域時調用
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@"進入監聽區域時調用");
}
// 離開監聽區域時調用
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    NSLog(@"離開監聽區域時調用");
}
4>地理編碼

    這個方法只須要頭文件聲明#import <CoreLocation/CoreLocation.h>。而與以上方法不一樣,是不須要實現代理,只須要簡單實現編碼對象的方法atom

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //1.建立地理編碼對象
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    
    // 2.利用地理編碼對象編碼
    // 根據傳入的地址獲取該地址對應的經緯度信息
    [geocoder geocodeAddressString:@"beijing" completionHandler:^(NSArray *placemarks, NSError *error) {
        
        if (placemarks.count == 0 || error != nil) {
            return ;
        }
        
        // placemarks地標數組, 地標數組中存放着地標, 每個地標包含了該位置的經緯度以及城市/區域/國家代碼/郵編等等..。
        for (CLPlacemark  *placemark in placemarks) {
            NSLog(@"name:%@ addressDictionary:%@ latitude:%f longitude:%f",
                  placemark.name,
                  placemark.addressDictionary,
                  placemark.location.coordinate.latitude,
                  placemark.location.coordinate.longitude);
            
            
            NSArray *address = placemark.addressDictionary[@"FormattedAddressLines"];
            //遍歷數組,讀取插入字符串
            NSMutableString *strM = [NSMutableString string];
            for (NSString *str in address) {
                [strM appendString:str];
            }
            NSLog(@"strm:%@",strM);
            
        }
        
    }];
}
5>反地理編碼

和地位編碼同樣,只須要簡單導入頭文件spa

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //1.建立地理編碼對象
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    
    CLLocation *location = [[CLLocation alloc] initWithLatitude:23.0f longitude:112.9f];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
        
        for (CLPlacemark *placemark in placemarks) {
            NSLog(@"name:%@ \n addressDictionary:%@ \n latitude:%f \n longitude:%f \n locality:%@",
                  placemark.name,                           //具體位置
                  placemark.addressDictionary,              //地理位置詳細信息
                  placemark.location.coordinate.latitude,   //經度
                  placemark.location.coordinate.longitude,  //緯度
                  placemark.locality);                      //城市名字
        }
    }];
}


4 第三方框架-LocationManager

一樣iOS8須要在info添加權限
代理

#import "INTULocationManager.h"

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 1.建立位置管理者
    INTULocationManager *mgr = [INTULocationManager sharedInstance];
    
    // 2.利用位置管理者獲取位置
    /*
     INTULocationAccuracy 精確度,包括更新的位置和時間
     timeout              延時時間
     status               發送狀態
     */
    [mgr requestLocationWithDesiredAccuracy:INTULocationAccuracyRoom  timeout:5 delayUntilAuthorized:YES block:^(CLLocation *currentLocation, INTULocationAccuracy achievedAccuracy, INTULocationStatus status) {
        if (status == INTULocationStatusSuccess) {
            NSLog(@"獲取位置成功 %f %f", currentLocation.coordinate.latitude , currentLocation.coordinate.longitude);
        }else if(status ==  INTULocationStatusError)
        {
            NSLog(@"獲取失敗");
        }
    }];
}

相關文章
相關標籤/搜索