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

9.3  方向監測
擁有GPS硬件的設備能夠生成設備的當前方向(course屬性)和速度信息。iPhone設備攜帶的定位管理器能夠返回一個已經計算好的course值,經過這個值咱們能夠得到當前前進的方向,course值是0360之間的浮點數,值表示正北方向,90°值表示正東方向,180°值表示正南方向,270°值表示正西方向,程序能夠經過course值來檢測用戶位置的移動方向。除此以外,還能夠經過磁力計來獲取設備的真實方向。
提示: ios

地球是一個大磁場,磁力計的北極將會永遠真實地指向北方。 ide

 iOS 系統經過heading 屬性來獲取設備的真實方向。須要指出的是,並非全部的iOS 設備都支持heading 屬性,從iPhone 3gs 開始引入了磁力計,所以程序在獲取方向以前須要先測試該設備是否支持heading 。若是定位管理器支持heading 屬性,那麼CLLocationManager headingAvailable 屬性將會返回「YES 」。
使用CLLocationManager 獲取設備方向與獲取移動距離的步驟基本類似,只是此時不是檢測位置移動,而是檢測方向改變。
使用CLLocationManager 獲取設備方向的步驟以下。
建立CLLocationManager 對象,該對象負責獲取定位相關信息。併爲該對象設置一些必要的屬性。
CLLocationManager 指定delegate 屬性,該屬性值必須是一個實現CLLocationManagerDelegate 協議的對象。實現CLLocationManagerDelegate 協議時可根據須要實現協議中特定的方法。
調用CLLocationManager startUpdatingHeading 方法獲取方向信息。獲取方向結束時,可調用stopUpdatingHeading 方法結束獲取方向信息。
當設備的方向改變時,iOS 系統將會自動激發CLLocationManager delegate 對象的locationManager:didUpdateHeading: 方法,而程序可經過重寫該方法來獲取設備方向。
 iOS 容許爲檢測方向改變設置以下屬性。
CLLocationDegrees headingFilter :設置只有當設備方向的改變值超過該屬性值時才激發delegate 的方法。
CLDeviceOrientation headingOrientation :設置設備當前方向。
監聽方向時返回的是一個CLHeading 對象,該對象包含以下屬性。
magneticHeading :該屬性返回設備與磁北的相對方向。
trueHeading :該屬性返回設備與真北的相對方向。   提示: 真北始終指向地理北極點;磁北則對應於隨時間變化的地球磁場北極。 iOS 系統使用一個計算後的偏移量(稱爲誤差)來肯定這二者之間的差別。

headingAccuracy :該屬性返回方向值的偏差範圍。
timestamp :該屬性返回方向值的生成時間。
x :獲取該設備在 X 方向上監聽獲得的原始磁力值,該磁力值的強度單位是微特斯拉。
y :獲取該設備在 Y 方向上監聽獲得的原始磁力值,該磁力值的強度單位是微特斯拉。
z :獲取該設備在 Z 方向上監聽獲得的原始磁力值,該磁力值的強度單位是微特斯拉。
在啓用該功能的iOS 設備上,即便用戶在Settings 應用中關閉了定位更新,磁向更新仍然可使用。此外,使用heading 服務的應用不會提示用戶受權問題,所以磁向信息不會泄露用戶的隱私,應用程序能夠隨便使用它。
須要說明的是,trueHeading 屬性須要與位置探測功能一塊兒使用,iOS 系統須要設備的位置來計算肯定真北所須要的誤差。誤差隨地理位置的變化而變化,好比北京的誤差不一樣於東京的誤差,也不一樣於新加坡和馬來西亞的誤差等。有一些地方根本不能使用磁力計進行讀數。
除此以外,在某些特殊位置例若有強磁、強電干擾的地方,磁力計可能沒法使用。
實例:指南針 此實例將會示範如何使用磁力計來獲取設備方向,而後根據設備方向來建立一個指南針應用。新建一個Single View Application ,無須修改界面設計文件,直接在應用的視圖控制器類的實現部分建立界面,並讓應用中顯示方向的圖片隨着設備方向自動旋轉便可。
下面是該應用的視圖控制器類的實現部分代碼。

程序清單:codes/09/9.3/Compass/Compass/FKViewController.m測試

@interface FKViewController () <CLLocationManagerDelegate>
{
    CALayer* znzLayer;
}
@property (nonatomic , strong)CLLocationManager *locationManager;
@end
@implementation FKViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 若是磁力計可用,則開始監聽方向改變
    if([CLLocationManager headingAvailable])
    {
        // 建立顯示方向的指南針圖片Layer
        znzLayer = [[CALayer alloc] init];
        NSInteger screenHeight = [UIScreen mainScreen].bounds.size.height;
        NSInteger y = (screenHeight - 320) / 2;
        znzLayer.frame = CGRectMake(0 , y , 320, 320);
        // 設置znzLayer顯示的圖片
        znzLayer.contents = (id)[[UIImage p_w_picpathNamed:@"znz.png"] CGImage];
        // 將znzLayer添加到系統的UIView中
        [self.view.layer addSublayer:znzLayer];
        // 建立CLLocationManager對象
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
        [self.locationManager startUpdatingHeading];
    }
    // 若是磁力計不可用,則使用UIAlertView顯示提示信息
    else
    {
        // 使用警告框提醒用戶
        [[[UIAlertView alloc] initWithTitle:@"提醒"
            message:@"您的設備不支持磁力計" delegate:self
            cancelButtonTitle:@"肯定" otherButtonTitles: nil]
            show];
    }
}
// 當成功獲取設備的方向值後激發該方法
-(void)locationManager:(CLLocationManager *)manager
    didUpdateHeading:(CLHeading *)newHeading
{
    // 將設備的方向角度換算成弧度
    CGFloat headings = -1.0f * M_PI * newHeading.magneticHeading / 180.0f;
    // 建立不斷改變CALayer的transform屬性的屬性動畫
    CABasicAnimation* anim = [CABasicAnimation
        animationWithKeyPath:@"transform"];
    CATransform3D fromValue = znzLayer.transform;
    // 設置動畫開始的屬性值
    anim.fromValue = [NSValue valueWithCATransform3D: fromValue];
    // 繞Z軸旋轉heading弧度的變換矩陣
    CATransform3D toValue = CATransform3DMakeRotation(headings , 0 , 0 , 1);
    // 設置動畫結束的屬性
    anim.toValue = [NSValue valueWithCATransform3D: toValue];
    anim.duration = 0.5;
    anim.removedOnCompletion = YES;
    // 設置動畫結束後znzLayer的變換矩陣
    znzLayer.transform = toValue;
    // 爲znzLayer添加動畫
    [znzLayer addAnimation:anim forKey:nil];
}
-(BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager
{
    return YES;
}
@end

上面程序中的前兩行粗體字代碼用於爲CLLocationManager設置delegate屬性,接下來程序調用該對象的startUpdatingHeading方法開始監聽設備的方向改變——當設備的方向改變時,系統會自動激發CLLocationManager設置delegatelocationManager:didUpdateHeading:方法,程序的視圖控制器重寫了該方法,並在該方法中獲取設備方向,而後將圖片「反轉」相應的角度,從而讓圖片的北極老是指向真實的北極。動畫

編譯、運行該應用(要在真機上測試該應用,由於iOS模擬器不支持磁力計),將能夠看到如圖9.5所示的效果。atom


155939_xXtl_262659.jpg

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

110624_Bbvc_262659.jpg
相關文章
相關標籤/搜索