溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

瘋狂ios講義之使用CoreLocation定位(2)

發(fā)布時間:2020-08-08 08:21:19 來源:網(wǎng)絡 閱讀:2276 作者:fkJava李剛 欄目:移動開發(fā)

9.2獲取定位信息


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

CLLocationManager定位管理器類。

CLLocationManagerdelegate該協(xié)議代表定位管理器的delegate協(xié)議。實現(xiàn)該協(xié)議的對象可負責處理CLLocationManager的定位事件。

CLLocation該對象代表位置。該對象包含了當前設備的經(jīng)度、緯度、高度、速度、路線等信息還包含了該定位信息的水平精確度、垂直精確度以及時間戳信息。

CLHeading該對象代表設備的移動方向。

CLRegion該對象代表一個區(qū)域。一般程序不會直接使用該類而是使用它的兩個子類即CLCircularRegion圓形區(qū)域和CLBeaconRegion藍牙信號區(qū)。

除此之外CoreLocation框架還涉及一個CLLocationCoordinate2D結構體變量該結構體變量包含經(jīng)度、緯度兩個值。其中CLLocation對象的coordinate屬性就是一個CLLocationCoordinate2D結構體變量。

了解CoreLocation提供的這些API之后接下來即可通過這些API進行定位了。

9.2.1 獲取位置信息

使用CoreLocation.framework進行定位只要如下3步即可。

創(chuàng)建CLLocationManager對象該對象負責獲取定位相關信息。并為該對象設置一些必要的屬性。

CLLocationManager指定delegate屬性該屬性值必須是一個實現(xiàn)CLLocationManagerDelegate協(xié)議的對象。實現(xiàn)CLLocationManagerDelegate協(xié)議時可根據(jù)需要實現(xiàn)協(xié)議中特定的方法。

調用CLLocationManagerstartUpdatingLocation方法獲取定位信息。定位結束時可調用stopUpdatingLocation方法結束獲取定位信息。

注意    

    為了在iOS應用中使用CoreLocation.framework需要完成兩件事情①為應用添加CoreLocation.framework框架②在需要使用定位服務及相關類的源文件中使用“#import <CoreLocation/CoreLocation.h>”導入CoreLocation.framework的頭文件。本章絕大部分示例都使用了CoreLocation.framework因此都需要執(zhí)行上面兩步操作。

從上面介紹不難看出使用CoreLocation進行定位的關鍵就是CLLocationManager對象及其delegate對象。其中CLLocationManager負責獲取定位信息而delegate則負責處理定位事件——通過這些事件即可獲取設備所在位置。

CLLocationManager還提供了如下類方法來判斷當前設備的定位相關服務狀態(tài)。

+ locationServicesEnabled返回當前定位服務是否可用。

+ deferredLocationUpdatesAvailable返回延遲定位更新是否可用。

+ significantLocationChangeMonitoringAvailable返回重大位置改變監(jiān)聽是否可用。

+ headingAvailable返回該設備是否支持磁力計計算方向。

+ isRangingAvailable返回藍牙信號范圍服務是否可用。這是iOS 7新增的方法。

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

pausesLocationUpdatesAutomatically設置iOS設備是否可暫停定位來節(jié)省電池的電量。如果該屬性設為“YES”則當iOS設備不再需要定位數(shù)據(jù)時iOS設備可以自動暫停定位。

distanceFilter設置CLLocationManager的自動過濾距離。也就是說只有當設備在水平方向的位置改變超過該數(shù)值以米為單位指定的距離時才會生成一次位置改變的信號。

desiredAccuracy設置定位服務的精度。該屬性值支持kCLLocationAccuracyBestForNavigation導航級的最佳精確度、kCLLocationAccuracyBest最佳精確度、kCLLocationAccuracy NearestTenMeters10米誤差、kCLLocationAccuracyHundredMeters百米誤差、kCLLocationAccuracyKilometer千米誤差、kCLLocationAccuracyThreeKilometers三千米誤差等常量值。當然也可直接指定一個浮點數(shù)作為定位服務允許的誤差。

activityType設置定位數(shù)據(jù)的用途。該屬性支持CLActivityTypeOther定位數(shù)據(jù)作為普通用途、CLActivityTypeAutomotiveNavigation定位數(shù)據(jù)作為車輛導航使用、CLActivityTypeFitness定位數(shù)據(jù)作為步行導航使用和CLActivityTypeOtherNavigation定位數(shù)據(jù)作為其他導航使用這幾個枚舉值之一。

接下來通過示例來示范使用CoreLocation定位iOS設備的位置。

創(chuàng)建一個Single View Application該項目包含一個應用程序委托類、一個視圖控制器類和Main.storyboard界面設計文件。打開該項目的界面設計文件向其中添加5個文本框分別用于顯示當前設備的經(jīng)度、緯度、高度、速度和方向并在界面上添加一個UIButton按鈕。

為了在程序中訪問界面上的5個文本框需要將它們分別綁定到視圖控制器類的longitudeTxt、latitudeTxt、altitudeTxt、speedTxt、courseTxt5IBOutlet屬性為了讓程序能響應按鈕的點擊事件還需要為按鈕的“Touch Up Inside”事件綁定bnTapped:事件處理方法。

下面是該視圖控制器類的實現(xiàn)部分代碼。

程序清單codes/09/9.2/LocationTest/LocationTest/FKViewController.m

@interface FKViewController () <CLLocationManagerDelegate>
@property (strong,nonatomic)CLLocationManager *locationManager;
@end
@implementation FKViewController
- (void)viewDidLoad
{  
    [super viewDidLoad];
    // 創(chuàng)建CLLocationManager對象
    self.locationManager = [[CLLocationManager alloc]init];
}
- (IBAction)bnTapped:(id)sender
{
    // 如果定位服務可用
    if([CLLocationManager locationServicesEnabled])
    {
        NSLog( @"開始執(zhí)行定位服務" );
        // 設置定位精度最佳精度
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        // 設置距離過濾器為50米表示每移動50米更新一次位置
        self.locationManager.distanceFilter = 50;
        // 將視圖控制器自身設置為CLLocationManager的delegate
        // 因此該視圖控制器需要實現(xiàn)CLLocationManagerDelegate協(xié)議
        self.locationManager.delegate = self;
        // 開始監(jiān)聽定位信息
        [self.locationManager startUpdatingLocation];
    }
    else
    {
        NSLog( @"無法使用定位服務" );
    }
}
// 成功獲取定位數(shù)據(jù)后將會激發(fā)該方法
-(void)locationManager:(CLLocationManager *)manager
    didUpdateLocations:(NSArray *)locations
{
    // 獲取最后一個定位數(shù)據(jù)
    CLLocation* location = [locations lastObject];
    // 依次獲取CLLocation中封裝的經(jīng)度、緯度、高度、速度、方向等信息
    self.latitudeTxt.text = [NSString stringWithFormat:@"%g",
        location.coordinate.latitude];
    self.longitudeTxt.text = [NSString stringWithFormat:@"%g",
        location.coordinate.longitude];
    self.altitudeTxt.text = [NSString stringWithFormat:@"%g",
        location.altitude];
    self.speedTxt.text = [NSString stringWithFormat:@"%g",
        location.speed];
    self.courseTxt.text = [NSString stringWithFormat:@"%g",
        location.course];
}
// 定位失敗時激發(fā)的方法
- (void)locationManager:(CLLocationManager *)manager
    didFailWithError:(NSError *)error
{
    NSLog(@"定位失敗: %@",error);
}
@end

上面程序中的第1段粗體字代碼為CLLocationManager對象設置了屬性之后關鍵是將該視圖控制器設置為CLLocationManagerdelegate程序調用CLLocationManagerstartUpdatingLocation方法開始獲取定位數(shù)據(jù)。

由于程序指定該視圖控制器作為CLLocationManagerdelegate因此該視圖控制器需要實現(xiàn)CLLocationManagerDelegate協(xié)議并實現(xiàn)該協(xié)議中定位相關的兩個事件處理方法。當程序成功獲取定位數(shù)據(jù)時將會激發(fā)delegatelocationManager:didUpdateLocations:方法因此上面視圖控制器類實現(xiàn)了該方法并在該方法中獲取最后一個定位數(shù)據(jù)CLLocation對象。

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

altitude該屬性表示當前設備的海拔高度單位是米。

coordinate該屬性返回一個CLLocationCoordinate2D結構體變量該結構體變量中包含經(jīng)度、緯度信息。

course該屬性表示當前設備前進的方向。該值為表示向北90°表示向東180°表示向南270°表示向西。

horizontalAccuracy該屬性表明定位信息的水平精確度。將返回的坐標作為圓心并將水平精確度視為半徑。真正的設備位置落在此圓內的某處。此圓越小位置就越精確此圓越大則位置越不精確。如果精確度為負值則表明測量精確度失敗。

verticalAccuracy該屬性表明定位信息的垂直精確度。也就是說iOS設備的實際高度在該定位信息的高度加或減該屬性值的范圍內。

timestamp該屬性返回定位信息的返回時間。

speed該屬性表示返回設備的移動速度單位是米/秒。實際上該屬性適用于行車速度而不太適用于步行速度。

每個iOS應用第一次使用定位功能時都會因為權限問題而彈出是否允許當前應用程序獲取定位操作權限的提示框如圖9.1所示。

瘋狂ios講義之使用CoreLocation定位(2)

9.1 詢問用戶是否允許該應用使用定位功能

單擊“OK”按鈕即可在Xcode控制器中看到“開始執(zhí)行定位服務”的提示信息但可能依然看不到程序界面上有任何輸出——此時我們可以通過模擬器來模擬設備的位置。

9.2.2使用iOS模擬器模擬位置

iOS模擬器本身并不能作為GPS接收機因此無法得到定位信息但為了方便程序員測試定位應用iOS模擬器可以模擬定位信息。

啟動iOS模擬器之后即可通過iOS模擬器主菜單中的“調試”→“位置”來模擬iOS設備的位置該菜單如圖9.2所示。

瘋狂ios講義之使用CoreLocation定位(2)

9.2所示菜單支持如下幾種位置信息。

自定位置開發(fā)者可以自行輸入位置的經(jīng)度值、緯度值。

City Bicycle Ride模擬設備攜帶者在城市中騎車移動。

City Run模擬設備攜帶者在城市中跑動。

Freeway Drive模擬設備攜帶者在高速公路中駕車。

如果選擇“Freeway Driver”來模擬該設備攜帶者在高速公路中駕車則可以看到該應用顯示如圖9.3所示。

瘋狂ios講義之使用CoreLocation定位(2)

9.2.3監(jiān)控行車速度和行車距離

上一個示例是通過CLLocation對象來獲取設備的移動速度和移動方向但這種移動速度屬性適用于行車速度而不太適用于步行速度。如果希望程序計算平均移動速度則只要不斷地累計設備的移動距離和移動時間再用距離除以時間即可得到設備的平均移動速度。

下面通過一個示例來計算設備的平均移動速度。新建一個Single View Application打開該應用的Main.storyboard界面設計文件向該界面設計文件中拖入一個UITextView控件用于顯示該設備的移動速度。為了在程序中訪問該UITextView控件程序將它綁定到視圖控制器的showView控件。

接下來修改視圖控制器類在視圖控制器類中通過設備的移動距離和移動時間來計算速度。下面是該視圖控制器類的實現(xiàn)部分代碼。

程序清單codes/09/9.2/SpeedMonitor/SpeedMonitor/FKViewController.m

#import "FKViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface FKViewController () <CLLocationManagerDelegate>
@property (nonatomic , retain) CLLocationManager *locationManager;
@property (nonatomic , retain) CLLocation *prevLocation;
@property (nonatomic , assign) CGFloat sumDistance;
@property (nonatomic , assign) CGFloat sumTime;
@end
@implementation FKViewController
- (void) viewDidLoad
{
    [super viewDidLoad];
    // 創(chuàng)建CLLocationManager對象
    self.locationManager = [[CLLocationManager alloc] init];
}
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // 設置定位精度最佳精度
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    // 設置距離過濾器為50米表示每移動50米更新一次位置
    self.locationManager.distanceFilter = 50;
    // 將視圖控制器自身設置為CLLocationManager的delegate
    // 因此該視圖控制器需要實現(xiàn)CLLocationManagerDelegate協(xié)議
    self.locationManager.delegate = self;
    // 開始監(jiān)聽定位信息
    [self.locationManager startUpdatingLocation];
    NSLog(@"開始執(zhí)行定位服務" );
}
// 定位失敗時激發(fā)的方法
- (void)locationManager:(CLLocationManager *)manager
    didFailWithError:(NSError *)error
{
    NSLog(@"定位失敗: %@",error);
}
// 成功獲取定位數(shù)據(jù)后將會激發(fā)該方法
-(void)locationManager:(CLLocationManager *)manager
    didUpdateLocations:(NSArray *)locations
{
    // 獲取最后一個定位數(shù)據(jù)
    CLLocation* newLocation = [locations lastObject];
    if(newLocation.horizontalAccuracy < kCLLocationAccuracyHundredMeters)
    {
        if(self.prevLocation)
        {
            // 計算本次定位數(shù)據(jù)與上次定位數(shù)據(jù)之間的時間差
            NSTimeInterval dTime = [newLocation.timestamp
                timeIntervalSinceDate:self.prevLocation.timestamp];
            // 累計行車時間
            self.sumTime += dTime;
            // 計算本次定位數(shù)據(jù)與上次定位數(shù)據(jù)之間的距離
            CGFloat distance = [newLocation
                distanceFromLocation:self.prevLocation];
            // 如果距離小于1米則忽略本次數(shù)據(jù)直接返回該方法
            if(distance < 1.0f)
            {
                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];
            self.showView.text = speedFeedback;
        }
        self.prevLocation = newLocation;
    }
}
@end

上面程序中的兩行粗體字代碼分別用于計算本次定位數(shù)據(jù)與上次定位數(shù)據(jù)之間的時間差、距離用此距離除以時間即可得到該設備的當前速度。除此之外該程序還定義了一個sumDistance屬性來保存設備移動的總距離并定義了一個sumTime來保存設備移動的總時間用設備移動的總距離除以設備移動的總時間即可獲取該設備移動的平均速度。

提示

iOS系統(tǒng)獲取的前后兩次定位數(shù)據(jù)的時間差以秒為單位前后兩次定位數(shù)據(jù)之間的距離以米為單位因此直接用距離除以時間得到速度單位為米/秒。如果程序希望以千米/小時作為速度單位則需要乘以3.6。

編譯、運行該程序并選擇“Freeway Driver”來模擬設備攜帶者在高速公路中駕車將可以看到該應用顯示如圖9.4所示的結果。

瘋狂ios講義之使用CoreLocation定位(2)

————本文節(jié)選自《瘋狂ios講義下》

瘋狂ios講義之使用CoreLocation定位(2)


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI