疯狂ios讲义之使用CoreLocation定位(3)

9.3  方向监测
拥有GPS硬件的设备可以生成设备的当前方向(course属性)和速度信息。iPhone设备携带的定位管理器可以返回一个已经计算好的course值,通过这个值我们可以获得当前前进的方向,course值是0360之间的浮点数,值表示正北方向,90°值表示正东方向,180°值表示正南方向,270°值表示正西方向,程序可以通过course值来检测用户位置的移动方向。除此之外,还可以通过磁力计来获取设备的真实方向。
提示:

地球是一个大磁场,磁力计的北极将会永远真实地指向北方。

 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 imageNamed:@"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所示的效果。


155939_xXtl_262659.jpg

————本文节选自《疯狂ios讲义(下)》

110624_Bbvc_262659.jpg


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值