疯狂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
相关文章
相关标签/搜索