疯狂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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@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


 

本文转自fkJava李刚 51CTO博客,原文链接:http://blog.51cto.com/javaligang/1389731 ,如需转载请自行联系原作者


相关文章
|
4月前
|
iOS开发
ios中,输入框获得焦点时,页面输入框被遮盖,定位的元素位置错乱
ios中,输入框获得焦点时,页面输入框被遮盖,定位的元素位置错乱
35 1
|
8月前
|
iOS开发
iOS 第三方dSYM定位BUG
iOS 第三方dSYM定位BUG
92 0
|
定位技术 iOS开发
iOS iPhone 修改手机定位虚拟定位
iOS iPhone 修改手机定位虚拟定位
iOS iPhone 修改手机定位虚拟定位
|
定位技术 API 开发工具
iOS开发-百度地图基本定位和罗盘跟随的使用,附加地理编码和反地理编码
iOS开发-百度地图基本定位和罗盘跟随的使用,附加地理编码和反地理编码
130 0
iOS开发-百度地图基本定位和罗盘跟随的使用,附加地理编码和反地理编码
|
定位技术 iOS开发
iOS模拟动态定位的测试方案
iOS模拟动态定位的测试方案
145 0
iOS模拟动态定位的测试方案
|
定位技术 iOS开发
iOS移动应用模拟定位的非侵入式测试方案
iOS移动应用模拟定位的非侵入式测试方案
337 0
iOS移动应用模拟定位的非侵入式测试方案
|
API 开发工具 iOS开发
iOS定位的使用:地理/逆地理编码/判断目标经纬度是否在大陆
iOS定位的使用:地理/逆地理编码/判断目标经纬度是否在大陆
631 0
iOS定位的使用:地理/逆地理编码/判断目标经纬度是否在大陆
|
测试技术 定位技术 开发工具
iOS设备限制境外定位(支付交易风险控制策略)
iOS设备限制境外定位(支付交易风险控制策略)
271 0
iOS设备限制境外定位(支付交易风险控制策略)
|
API 定位技术 开发工具
iOS14 定位适配:1、向用户申请临时开启一次精确位置权限的方案2、高德定位SDK适配
iOS14 定位适配:1、向用户申请临时开启一次精确位置权限的方案2、高德定位SDK适配
1499 0
iOS14 定位适配:1、向用户申请临时开启一次精确位置权限的方案2、高德定位SDK适配
|
存储 监控 安全
[iOS研习记]——聊聊野指针与僵尸对象定位
在iOS项目开发中,或多或少的我们都会遇到一些Crash的情况,大部分Crash抛出的异常都是NSException层的,这类异常是OC层代码问题造成的,通常堆栈信息和异常的提示信息都非常明确,可以直接定位到出问题的代码,从而使这类问题的解决并不困难。可以引起Crash的异常除了NSException外,还有Unix层和Mach层的异常。
1546 0