你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 第九章:使用CoreLocation定位

第九章:使用CoreLocation定位

編輯:IOS開發綜合

CoreLocation框架(CoreLocation.framework)可用於定位設備當前的經緯度,通過該框架,應用程序可通過附近的蜂窩基站、WIFI信號或者GPS等信息計算用戶位置。

iOS SDK提供了CLLocationManager、CLLocationManagerDelegate來處理設備的定位信息,包括獲取設備的方向以及進行方向檢測等。其中CLLocationManager是整個CoreLocation框架的核心,定位、方向檢測、區域檢測等都由該API完成;而CLLocationManagerDelegate是一個協議,實現該協議的對象可作為CLLocationManager的delegate對象,負責處理CLLocationManager的定位、方向檢測、區域檢測等相關事件。除此之外,iOS還提供了CLLocation(代表位置信息)、CLLHeading(代表設備方向)、CIRegion(代表區域)等API,這些API與CLLocationManager、CLLocationManagerDelegate共同組成了iOS的CoreLocation框架。

一、iOS的定位支持

1、GPS衛星定位

GPS是英文:Global Positioning System(全球定位系統)的簡稱;該定位系統由3部分組成,即由GPS衛星組成的空間部分、若干地面站的控制部分和普通用戶手中的接收機這3部分。

與基站、WIFI定位相比,GPS定位耗電量最大,速度最慢,但是精度最高。

2、基站定位

每個手機基站都有一個標識符,iOS設備可以搜集周圍所有收到信號的基站和它們的標識符,通過聯網發送到蘋果雲端服務器,再由服務器根據這些基站的位置信息查詢並計算出當前位置,然後把該定位信息返回到手機。

3、WIFI定位

iOS設備通過無線卡搜集周圍所有的WIFI熱點,獲得它們的MAC地址,然後通過Apple的雲端服務器查詢該WiFi熱點是否已經登記,如果已經登記,即可獲取該WiFi熱點的位置,最後通過對多個WiFi熱點折中計算得到當前位置並返給iOS設備。

二、獲取定位信息

iOS開發者使用CoreLocation.framework框架進行定位非常簡單,CoreLocation框架的常用API主要有如下幾個:

(1)、CLLocationManager:定位管理器類; (2)、CLLocationManagerDelegate:該協議代表定位管理器的delegate協議。實現該協議的對象可負責處理CLLocationManager的定位事件; (3)、CLLocation:該對象代表位置。該對象包含了當前設備的經度、緯度、高度、速度、路線等信息,還包含了該定位信息的水平精確度、垂直精確度以及時間戳信息; (4)、CLHeading:該對象代表設備的移動方向; (5)、CLRegion:該對象代表一個區域。一般程序不會直接使用該類,而是使用它的兩個子類,即CLCircularRegion(圓形區域)和CLBeaconRegion(藍牙信號區);

除此之外,CoreLocation框架還涉及一個CLLocationCoordinate2D結構體變量,該幾诶夠提變量包含經度、緯度兩個值,其中CLLocation對象的coordinate屬性就是一個CLLocationCoordinate2D結構體變量。

1、獲取位置信息

 使用CoreLocation.framework進行定位如下步驟:
①、創建CLLocationManager對象,該對象負責獲取定位相關信息。並為該對象設置一些必要的屬性; ②、為CLLocationManager指定delegate屬性,該屬性必須是一個實現CLLocationManagerDelegate協議的對象。實現CLLocationManagerDelegate協議時刻根據需要實現協議中特定的方法; ③、調用CLLocationManager的startUpdatingLocation方法獲取定位信息。定位結束時,可調用stopUpdatingLocation方法結束獲取定位信息。

提示:為了在iOS應用中使用CoreLocation.framework,需要完成兩件事情:
①、為應用添加CoreLocation.framework框架;
②、在需要使用定位服務及相關類的源文件重使用#import < CoreLocation/CoreLocation.h >導入CoreLocation.framework的頭文件。

CoreLocationManager提供了如下類方法判斷當前設備的定位相關服務狀態:

(1)、 + (BOOL)locationServicesEnabled __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);//返回當前定位服務是否可用;
(2)、 + (BOOL)deferredLocationUpdatesAvailable __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);//返回延遲定位更新是否可用;
(3)、 + (BOOL)significantLocationChangeMonitoringAvailable __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);//返回重大位置監聽是否可用;
(4)、 + (BOOL)headingAvailable
__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);//返回該設備是否支持磁力計計算方向;
(5)、 + (BOOL)isRangingAvailable __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);//返回藍牙信號范圍是否可用。

除此之外,在使用CLLocationManager開始定位之前,還可為該對象設備如下屬性:

(1)、 @property(assign, nonatomic) BOOL pausesLocationUpdatesAutomatically __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);設置iOS設備是否可暫停定位來節省電池的電量;如果該屬性設為『YES』,則當iOS設備不再需要定位數據時,iOS設備可以自動暫停定位; (2)、 @property(assign, nonatomic) CLLocationDistance distanceFilter;設置CLLocationManager的自動過濾距離。也就是說,只有當設備在水平方向的位置改變超過該數值(以米為單位)指定的距離時才會生成一次位置變化的信號; (3)、 @property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;設置定位服務的靜度。該屬性值支持
extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);(導航級的最佳精確度);
extern const CLLocationAccuracy kCLLocationAccuracyBest;(最佳精確度);
extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;(10米誤差);
extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;(百米誤差);
extern const CLLocationAccuracy kCLLocationAccuracyKilometer;(千米誤差);
extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;(1三千米誤差)

等常量值。當然,也可直接指定一個浮點數作為定位服務允許的誤差;

(4)、 @property(assign, nonatomic) CLActivityType activityType __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);設置定位數據的用途。該屬性支持
{
    CLActivityTypeOther = 1,(定位數據作為普通用途)
    CLActivityTypeAutomotiveNavigation,(定位數據作為車輛導航使用)
    CLActivityTypeFitness,(定位數據作為步行導航使用)
    CLActivityTypeOtherNavigation(定位數據作為其他導航使用)
};

注意:iOS8中使用CoreLocation定位

(1)、在使用CoreLocation需要調用如下函數
iOS8對定位進行了一些修改,其中包括定位授權的方法,CLLocationManager增加了如下兩個方法:

①、始終允許訪問位置信息

- (void)requestAlwaysAuthorization __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0);

②、使用應用程序期間允許方位位置數據

- (void)requestWhenInUseAuthorization __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0);
(2)、在Info.plist文件中添加如下配置:

①、NSLocationAlwaysUsageDescription

②、NSLocationWhenInUseUsageDescription

這兩個鍵的值就是授權alert的描述,實例配置如下:
這裡寫圖片描述
Demo如下:

- (void)clickBtn{
    //如果定位服務可用
    if ([CLLocationManager locationServicesEnabled]) {
        NSLog(@"開始執行定位服務");
        //設置定位精度:最佳精度
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        //設置距離過濾器為50米,表示每移動50米更新一次位置
        self.locationManager.distanceFilter = 50;
        //將試圖控制器自身設置為CLLocationManager的delegate
        //因此該試圖控制器需要實現CLLocationManagerDelegate協議
        self.locationManager.delegate = self;
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
        {
            [self.locationManager requestWhenInUseAuthorization];
            [self.locationManager requestAlwaysAuthorization];
        }
        //開始監聽定位信息
        [self.locationManager startUpdatingLocation];
    }else{
        NSLog(@"無法使用定位服務!!!");
    }
}
#pragma mark -- CLLocationManagerDelegate
//成功獲取定位數據後將會激發該方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
    //獲取最後一個定位數據
    CLLocation* location = [locations lastObject];
    //依次獲取CLLocation中封裝的經度、緯度、高度、速度、方向等信息
    NSLog(@"經度:%g,緯度:%g,高度:%g,速度:%g,方向:%g",location.coordinate.latitude,location.coordinate.longitude,location.altitude,location.speed,location.course);
}
//定位失敗時激發的方法
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    NSLog(@"定位失敗:%@",error);
}

CLLocation對象包含如下屬性,這些屬性包含了定位相關信息:

(1)、 @property(readonly, nonatomic) CLLocationDistance altitude;//該屬性表示當前設備的海拔高度,單位是米;
(2)、 @property(readonly, nonatomic) CLLocationCoordinate2D coordinate;//該屬性返回一個CLLocationCoordinate2D結構體變量,該結構體變量中包含經度、緯度信息;
(3)、 @property(readonly, nonatomic) CLLocationDirection course __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_2_2);//該屬性表示當前設備前進的方向。該值為0°表示向北,90°表示向東,180°表示向南,270°表示向西;
(4)、 @property(readonly, nonatomic) CLLocationAccuracy horizontalAccuracy;//該屬性表明定位信息的水平精確度。將返回的坐標作為圓心,並將水平精確度視為半徑。真正的設備位置落在此圓內的某處。此圓越小,位置就越精確;此圓越大,則位置越不精確。如果精確度為負值,則表明測量精確度失敗;
(5)、 @property(readonly, nonatomic) CLLocationAccuracy verticalAccuracy;//該屬性標明定位信息的垂直精確度。也就是說,iOS設備的實際高度在該定位信息的高度加或減該屬性值的范圍內;
(6)、 @property(readonly, nonatomic, copy) NSDate *timestamp;//該屬性返回定位信息的返回時間;
(7)、 @property(readonly, nonatomic) CLLocationSpeed speed __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_2_2);//該屬性表示返回設備的移動速度,單位是米/秒。實際上,該屬性適用於行車減速,而不太適用於步行速度。

2、使用iOS模擬器模擬位置

這裡寫圖片描述

①、自定位置:開發者可以自行輸入位置的經度值、緯度值; ②、City Bicycle Ride:模擬設備攜帶者在城市中騎車移動; ③、City Run:模擬設備攜帶者在城市中跑步; ④、Freeway Drive:模擬設備攜帶者再告訴公路中駕車;

3、監控行車速度和行車距離

如果開發者希望計算平均移動速度,則只要不斷的累計設備的移動距離和移動時間,再用距離除以時間即可得到設備的平均移動速度。

例如:

#pragma mark -- CLLocationManagerDelegate
//成功獲取定位數據後將會激發該方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
    //獲取最後一個定位數據
    CLLocation* newLocation = [locations lastObject];
    if (newLocation.horizontalAccuracy < kCLLocationAccuracyHundredMeters) {
        if (self.prevLocation) {
            //計算本次定位數據與上次定位數據之間的時間差
            NSTimeInterval dTime = [newLocation.timestamp timeIntervalSinceDate:self.prevLocation.timestamp];
            //累計行車時間
            self.sumTime += dTime;
            CGFloat distance = [newLocation distanceFromLocation:self.prevLocation];
            //如果距離小於1米。則忽略本次數據,直接返回該方法
            if (distance < 1.f) {
                return;
            }
            self.sumDistance += distance;
            //計算移動速度,將米/秒換算成千米/小時,需要乘以3.6
            CGFloat speed = distance/dTime*3.6;
            //計算平均速度
            CGFloat avgSpeed = self.sumDistance/self.sumTime*3.6;
            NSString* speedFeedback = [NSString stringWithFormat:@"當前速度為:%g千米/小時,平均速度為:%g千米/小時。合計移動:%g前面",speed,avgSpeed,self.sumDistance/1000];
            NSLog(@"%@",speedFeedback);
        }
        self.prevLocation = newLocation;
    }
}

三、方向監測

擁有GPS硬件的設備可以生成設備的當前方向(couse屬性)和速度信息。iPhone設備攜帶的定位管理器可以返回一個已經計算好的course值,通過這個值我們可以獲得當前前進的方向,course值是0~360之間的浮點數,0°值表示正北方向,90°值表示正東方向,180°值表示正南方向,270°值表示正西方向,程序可以通過course值來檢測用戶位置的移動方向。

使用CLLocationManager獲取設備方向的步驟如下:

①、創建CLLocationManager對象,該對象負責獲取定位相關信息。並為該對象設備一些必要的屬性; ②、為CLLocationManager指定delegate屬性,該屬性必須是一個實現CLLocationManagerDelegate協議的對象。實現CLLocationManagerDelegate協議時刻根據需要實現協議中特定的方法。 ③、調用CLLocationManager的starUpdatingHeading方法獲取方向信息。獲取方向結束時,可調用stopUpdatingHeading方法結束獲取方向信息。

當設備的方向改變時,iOS系統將會自動激發CLLocationManager的delegate對象的

- (void)locationManager:(CLLocationManager *)manager
       didUpdateHeading:(CLHeading *)newHeading __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);

方法,而程序可通過重寫該方法來獲取設備方向;

iOS允許為檢測方向改變設置如下屬性:

①、CLLocationDegrees headingFilter:設置只有當設置方向的改變值超過該屬性值時才激發delegate方法; ②、CLDeviceOrientation headingOrientation:設置設備當前方向;

監聽方向時返回的是一個CLHeading對象,該對象包含如下屬性:

(1)、 @property(readonly, nonatomic) CLLocationDirection magneticHeading;//該屬性返回設備與磁北的相對方向;
(2)、 @property(readonly, nonatomic) CLLocationDirection trueHeading;//該屬性返回設備與真北的相對方向;
(3)、 @property(readonly, nonatomic) CLLocationDirection headingAccuracy;//該屬性返回方向值的錯誤范圍;
(4)、 @property(readonly, nonatomic, copy) NSDate *timestamp;//該屬性返回方向值的生成時間;
(5)、 @property(readonly, nonatomic) CLHeadingComponentValue x;//獲取該設備在X方向上監聽得到的原始磁力值,該磁力值的強度單位是微特斯拉;
(6)、 @property(readonly, nonatomic) CLHeadingComponentValue y;//獲取該設備在Y方向上監聽得到的原始磁力值,該磁力值的強度單位是微特斯拉;
(7)、 @property(readonly, nonatomic) CLHeadingComponentValue z;//獲取該設備在Z方向上監聽得到的原始磁力值,該磁力值的強度單位是微特斯拉;

實例:指南針

#import 
@interface ViewController ()
{
    CALayer* znzLayer;
}
@property (nonatomic ,strong) CLLocationManager* locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    //如果磁力計可用,則開始監聽方向改變;
    if ([CLLocationManager headingAvailable]) {
        //創建顯示方向的指南針Layer
        znzLayer = [[CALayer alloc]init];
        NSInteger screenHeight = [UIScreen mainScreen].bounds.size.height;
        NSInteger screenWidth = [UIScreen mainScreen].bounds.size.width;
        NSInteger y = (screenHeight - 320)/2;
        NSInteger x = (screenWidth - 320)/2;
        znzLayer.frame = CGRectMake(x, y, 320, 320);
        //設置znzLayer顯示的照片
        znzLayer.contents = (id)[[UIImage imageNamed:@"znz.png"]CGImage];
        //將znzLayer添加刀系統的UIView中
        [self.view.layer addSublayer:znzLayer];
        //創建CLLocationManager對象
        self.locationManager = [[CLLocationManager alloc]init];
        self.locationManager.delegate = self;
        [self.locationManager startUpdatingHeading];
    }else{
        //如果磁力計不可用告知
        NSLog(@"設備不支持磁力計");
    }
}
#pragma mark -- CLLocationManagerDelegate --
//當成功獲取設備的方向值激發該方法
- (void)locationManager:(CLLocationManager *)manager
       didUpdateHeading:(CLHeading *)newHeading{
    //以北為0°順時針增加
    NSLog(@"%g",newHeading.magneticHeading);
    //將設備的方向角度換算成弧度
    CGFloat headings = -1.0f*M_PI*newHeading.magneticHeading/180.0f;
    //創建不斷改變CALayer的transform屬性的屬性動畫
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"transform"];
    CATransform3D formValue = znzLayer.transform;
    //設置動畫開始的屬性值
    anim.fromValue = [NSValue valueWithCATransform3D:formValue];
    //繞z軸旋轉heading弧度的變換矩陣
    CATransform3D toValue = CATransform3DMakeRotation(headings, 0, 0, 1);
    anim.toValue = [NSValue valueWithCATransform3D:toValue];
    anim.duration = 0.1;
    //動畫完成後是否移除
    anim.removedOnCompletion = YES;
    //設置動畫結束後znzLayer的變換矩陣
    znzLayer.transform = toValue;
    //為znzLayer添加動畫
    [znzLayer addAnimation:anim forKey:nil];
}
- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager{
    return YES;
}

四、區域監測

如果希望iOS設備進入某個區域發出通知,那麼這種區域監測的功被稱為臨近警告;用戶設備不斷地臨近固定點,當與該固定點的距離小於指定范圍時,系統可以觸發相應的處理。用戶設備離開指定固定點,當與該固定點的距離大於指定范圍時,系統也可以出發相應的處理。

iOS的區域監測同樣可以使用CLLocationManager來實現,監聽設備是否進入/離開某個區域的步驟如下:

①、創建CLLocationManager對象,該對象負責獲取定位相關信息,並為該對象設置一些必要的屬性。對於區域監測而言,CLLocationManager對象需要設置monitoredRegions屬性,該屬性值用於設置該設備監聽的多個區域; ②、為CLLocationManager指定delegate屬性,該屬性值必須是一個實現CLLocationManagerDelegate協議的對象。實現
CLLocationManagerDelegate協議時刻根據需要實現協議中特定的方法; ③、調用CLLocationManager的startMonitoringForRegion:方法進行區域監測,區域監測結束時,可調用stopMonitoringForRegion:方法結束區域監測。

區域檢測

#import 
@interface ViewController ()
@property (nonatomic ,strong) CLLocationManager* locationManager;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    if ([CLLocationManager locationServicesEnabled]) {
        self.locationManager = [[CLLocationManager alloc]init];
        self.locationManager.delegate = self;
        //定義一個CLLocationCoordinate2D作為區域的圓心
        CLLocationCoordinate2D companyCenter;
        companyCenter.latitude = 23.126272;
        companyCenter.longitude = 113.395568;
        //使用CLCircularRegion創建一個圓形區域,半徑為500米
        CLRegion* fkit = [[CLCircularRegion alloc]initWithCenter:companyCenter radius:10000000000 identifier:@"fkit"];
        //開始監聽fkit區域
        [self.locationManager startMonitoringForRegion:fkit];
    }else{
        NSLog(@"該設備不支持定位");
    }
}
#pragma mark -- CLLocationManagerDelegate --
//進入指定區域以後將彈出提示框提示用戶
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
    [[[UIAlertView alloc]initWithTitle:@"區域監測提示" message:@"您已經【進入】區域" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]show];
}
//離開指定區域以後將彈出提示框提示用戶
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
    [[[UIAlertView alloc]initWithTitle:@"區域監測提示" message:@"您已經【離開】區域" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]show];
}
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved