利用Core Location定位:简单指南
在移动应用开发中,定位功能是一项非常实用的特性。Core Location为开发者提供了一种简单的方式来实现与定位相关的功能,让我们可以轻松地知道用户的位置以及他们何时移动。下面将详细介绍Core Location的使用方法。
1. Core Location基础
Core Location依赖的技术对开发者的应用程序是隐藏的。我们无需告诉Core Location使用GPS、三角测量还是WPS,只需告知所需的精度,它会从可用技术中选择最适合的方法来满足我们的请求。
2. 定位管理器(Location Manager)
Core Location API使用起来相当简单,主要使用的类是
CLLocationManager
,通常称为定位管理器。要与Core Location交互,首先需要创建定位管理器的实例:
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
创建实例后,它并不会立即开始轮询位置。还需要创建一个遵循
CLLocationManagerDelegate
协议的对象,并将其指定为定位管理器的代理。当定位信息可用或发生变化时,定位管理器会调用代理方法。确定位置的过程可能需要一些时间,甚至几秒钟。
3. 设置所需精度
设置代理后,还需要设置所需的精度。注意,不要指定超过实际需求的精度。因为要求的精度越高,消耗的电量可能就越多,而且也不能保证一定能获得所请求的精度。以下是设置代理和请求特定精度的示例:
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
精度使用
CLLocationAccuracy
值设置,这是一个双精度类型,单位为米。例如,指定
desiredAccuracy
为10,表示希望Core Location尽可能在10米范围内确定当前位置。除了
kCLLocationAccuracyBest
,还可以使用
kCLLocationAccuracyBestForNavigation
、
kCLLocationAccuracyNearestTenMeters
、
kCLLocationAccuracyHundredMeters
、
kCLLocationAccuracyKilometer
和
kCLLocationAccuracyThreeKilometers
。
4. 设置距离过滤器
默认情况下,定位管理器会通知代理设备位置的任何检测到的变化。通过指定距离过滤器,可以告诉定位管理器仅在位置变化超过一定量时才通知我们,这样可以减少应用程序的轮询次数。距离过滤器同样以米为单位。例如:
locationManager.distanceFilter = 1000.0f;
这表示iPhone至少移动1000米后,定位管理器才会通知其代理。如果想恢复到无过滤器的默认设置,可以使用常量
kCLDistanceFilterNone
:
locationManager.distanceFilter = kCLDistanceFilterNone;
与设置所需精度一样,要避免过于频繁地获取更新,以免浪费电池电量。
5. 启动定位管理器
准备好开始轮询位置时,告诉定位管理器启动:
[locationManager startUpdatingLocation];
启动后,它会开始工作,确定当前位置后调用代理方法。在停止之前,只要检测到的变化超过当前距离过滤器的设置,就会继续调用代理方法。
6. 明智使用定位管理器
如果只需要确定当前位置,不需要持续轮询,那么在获取到应用程序所需的信息后,应让定位代理停止定位管理器。如果需要持续轮询,也要尽快停止。因为只要从定位管理器获取更新,就会消耗用户的电池电量。停止定位管理器的方法如下:
[locationManager stopUpdatingLocation];
7. 定位管理器代理
定位管理器代理必须遵循
CLLocationManagerDelegate
协议,该协议定义了两个可选方法。一个是在确定当前位置或检测到位置变化时调用,另一个是在定位管理器遇到错误时调用。
8. 获取位置更新
当定位管理器要通知代理当前位置时,会调用
locationManager:didUpdateToLocation:fromLocation:
方法,该方法有三个参数:
- 第一个参数是调用该方法的定位管理器。
- 第二个参数是
CLLocation
对象,定义了设备的当前位置。
- 第三个参数是
CLLocation
对象,定义了上次更新的前一个位置。第一次调用该方法时,前一个位置对象为
nil
。
9. 使用CLLocation获取纬度和经度
位置信息通过
CLLocation
类的实例从定位管理器传递。该类有五个可能对应用程序有用的属性,纬度和经度存储在
coordinate
属性中。获取纬度和经度的方法如下:
CLLocationDegrees latitude = theLocation.coordinate.latitude;
CLLocationDegrees longitude = theLocation.coordinate.longitude;
CLLocation
对象还能显示定位管理器对纬度和经度计算的置信度。
horizontalAccuracy
属性描述了以坐标为中心的圆的半径,值越大,Core Location对位置的确定越不确定;半径非常小表示对确定的位置有很高的置信度。在地图应用中可以看到
horizontalAccuracy
的图形表示。
此外,
CLLocation
对象还有
altitude
属性,可告知海拔高度;
verticalAccuracy
属性表示对海拔确定的置信度;
timestamp
属性记录了定位管理器确定位置的时间。还可以使用
distanceFromLocation:
方法确定两个
CLLocation
对象之间的距离:
CLLocationDistance distance = [fromLocation distanceFromLocation:toLocation];
这个距离是大圆距离计算的结果,忽略了海拔属性,假设两点都在海平面上。
10. 错误通知
如果Core Location无法确定当前位置,会调用
locationManager:didFailWithError:
方法。最可能的错误原因是用户拒绝访问。第一次应用程序尝试确定位置时,屏幕会弹出一个警告框,询问是否允许当前程序访问位置信息。如果用户点击“不允许”,代理会收到错误代码
kCLErrorDenied
的通知。目前,定位管理器支持的另一个错误代码是
kCLErrorLocationUnknown
,表示无法确定位置,但会继续尝试。
11. 实践Core Location
下面通过一个小应用来检测iPhone的当前位置和程序运行期间的总行驶距离。具体步骤如下:
1. 在Xcode中,使用单视图应用模板创建一个新项目,命名为
WhereAmI
,并将设备系列设置为iPhone。
2. 打开
BIDViewController.h
文件,进行如下修改:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface BIDViewController : UIViewController <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) CLLocation *startingPoint;
@property (strong, nonatomic) IBOutlet UILabel *latitudeLabel;
@property (strong, nonatomic) IBOutlet UILabel *longitudeLabel;
@property (strong, nonatomic) IBOutlet UILabel *horizontalAccuracyLabel;
@property (strong, nonatomic) IBOutlet UILabel *altitudeLabel;
@property (strong, nonatomic) IBOutlet UILabel *verticalAccuracyLabel;
@property (strong, nonatomic) IBOutlet UILabel *distanceTraveledLabel;
@end
-
打开
BIDViewController.xib文件创建GUI。参考示例界面,从库中拖动12个标签到视图窗口。将6个标签放在屏幕左侧,右对齐并加粗,分别命名为“Latitude:”、“Longitude:”、“Horizontal Accuracy:”、“Altitude:”、“Vertical Accuracy:”和“Distance Traveled:”。另外6个标签左对齐,放在加粗标签旁边,并将它们连接到之前在头文件中定义的相应出口,然后删除每个标签中的文本。 -
保存更改后,返回Xcode,打开
BIDViewController.m文件,在文件顶部进行如下修改:
#import "BIDViewController.h"
@implementation BIDViewController
@synthesize locationManager;
@synthesize startingPoint;
@synthesize latitudeLabel;
@synthesize longitudeLabel;
@synthesize horizontalAccuracyLabel;
@synthesize altitudeLabel;
@synthesize verticalAccuracyLabel;
@synthesize distanceTraveledLabel;
// ...
-
在
viewDidLoad方法中插入以下代码来配置定位管理器:
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
-
在
viewDidUnload方法中插入以下代码清理出口:
- (void)viewDidUnload {
[super viewDidUnload];
self.locationManager = nil;
self.latitudeLabel = nil;
self.longitudeLabel = nil;
self.horizontalAccuracyLabel = nil;
self.altitudeLabel = nil;
self.verticalAccuracyLabel = nil;
self.distanceTraveledLabel = nil;
}
- 在文件末尾插入以下新方法:
#pragma mark -
#pragma mark CLLocationManagerDelegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if (startingPoint == nil)
self.startingPoint = newLocation;
NSString *latitudeString = [NSString stringWithFormat:@"%g\u00B0", newLocation.coordinate.latitude];
latitudeLabel.text = latitudeString;
NSString *longitudeString = [NSString stringWithFormat:@"%g\u00B0", newLocation.coordinate.longitude];
longitudeLabel.text = longitudeString;
NSString *horizontalAccuracyString = [NSString stringWithFormat:@"%gm", newLocation.horizontalAccuracy];
horizontalAccuracyLabel.text = horizontalAccuracyString;
NSString *altitudeString = [NSString stringWithFormat:@"%gm", newLocation.altitude];
altitudeLabel.text = altitudeString;
NSString *verticalAccuracyString = [NSString stringWithFormat:@"%gm", newLocation.verticalAccuracy];
verticalAccuracyLabel.text = verticalAccuracyString;
CLLocationDistance distance = [newLocation distanceFromLocation:startingPoint];
NSString *distanceString = [NSString stringWithFormat:@"%gm", distance];
distanceTraveledLabel.text = distanceString;
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSString *errorType = (error.code == kCLErrorDenied) ? @"Access Denied" : @"Unknown Error";
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error getting Location" message:errorType delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil];
[alert show];
}
12. 编译和运行
在编译程序之前,需要将
CoreLocation.framework
添加到项目中。操作步骤如下:
1. 点击项目导航器中的第一行(蓝色的
WhereAmI
图标)。
2. 点击
TARGETS
下的
WhereAmI
图标。
3. 点击
Build Phases
选项卡。
4. 展开
Link Binary With Libraries
disclosure triangle,添加
CoreLocation.framework
。
编译并运行应用程序,如果有条件在iPhone或iPad上运行,可以在应用运行时开车移动,观察数值的变化(当然,最好让其他人开车)。
总结
Core Location虽然底层技术复杂,但Apple提供了简单的接口,隐藏了大部分复杂性,使得在应用程序中添加与定位相关的功能变得非常容易。掌握了Core Location的使用方法后,就可以轻松地知道用户的位置以及他们何时移动。
以下是使用Core Location的基本流程图:
graph TD;
A[创建CLLocationManager实例] --> B[设置代理];
B --> C[设置所需精度];
C --> D[设置距离过滤器];
D --> E[启动定位管理器];
E --> F{获取位置更新};
F -- 成功 --> G[更新界面信息];
F -- 失败 --> H[处理错误];
G --> I{是否需要继续轮询};
I -- 否 --> J[停止定位管理器];
I -- 是 --> F;
在开发应用时,按照以上步骤操作,就能利用Core Location实现强大的定位功能。同时,要注意合理设置精度和距离过滤器,以减少电量消耗。
利用Core Location定位:简单指南
13. 技术细节分析
在使用Core Location时,有几个技术细节值得深入分析。
精度设置的影响
精度设置对应用的性能和电量消耗有显著影响。不同的精度级别对应不同的定位技术和资源消耗。以下是常见精度级别的对比:
| 精度级别 | 描述 | 适用场景 |
| ---- | ---- | ---- |
| kCLLocationAccuracyBest | 使用当前可用的最精确方法 | 需要高精度定位的应用,如导航应用 |
| kCLLocationAccuracyBestForNavigation | 使用其他传感器数据,精度更高 | 导航应用,对定位精度要求极高 |
| kCLLocationAccuracyNearestTenMeters | 精确到最近的10米 | 一些对精度要求较高的应用,如附近商家推荐 |
| kCLLocationAccuracyHundredMeters | 精确到最近的100米 | 一般性的位置服务,如城市级别的定位 |
| kCLLocationAccuracyKilometer | 精确到最近的1公里 | 对精度要求较低的应用,如天气应用 |
| kCLLocationAccuracyThreeKilometers | 精确到最近的3公里 | 对精度要求极低的应用,如大范围的统计分析 |
在选择精度级别时,应根据应用的实际需求进行选择,避免过度消耗电量。
距离过滤器的作用
距离过滤器可以减少不必要的位置更新,从而降低电量消耗。例如,在一个显示附近餐厅的应用中,不需要实时更新用户的位置,只需要在用户移动一定距离后更新即可。通过设置合适的距离过滤器,可以有效减少定位管理器的轮询次数。
14. 错误处理策略
当Core Location遇到错误时,需要合理处理以提供良好的用户体验。
用户拒绝访问
如果用户拒绝访问位置信息,应用应给出友好的提示,引导用户开启权限。例如,在
locationManager:didFailWithError:
方法中,可以添加如下代码:
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if (error.code == kCLErrorDenied) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"权限被拒绝" message:@"请在设置中开启位置权限以使用此功能" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];
} else {
NSString *errorType = @"Unknown Error";
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error getting Location" message:errorType delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil];
[alert show];
}
}
位置未知错误
当遇到
kCLErrorLocationUnknown
错误时,应用可以选择继续尝试定位,或者给出提示让用户检查设备的网络和定位设置。
15. 性能优化建议
为了提高应用的性能和用户体验,以下是一些性能优化建议:
及时停止定位
在不需要持续定位时,及时停止定位管理器,减少电量消耗。例如,在一个只需要获取用户当前位置的应用中,在获取到位置信息后,立即停止定位管理器:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// 获取到位置信息
// ...
[manager stopUpdatingLocation];
}
批量处理位置更新
如果应用需要处理大量的位置更新,可以考虑批量处理,减少UI更新的频率,提高性能。例如,可以设置一个计数器,每获取到一定数量的位置更新后,再更新一次界面。
16. 拓展应用场景
Core Location的应用场景非常广泛,除了前面提到的导航和附近商家推荐,还可以应用于以下场景:
运动记录
记录用户的运动轨迹和距离,如跑步、骑行等。可以利用
CLLocation
对象的
distanceFromLocation:
方法计算运动的总距离。
地理围栏
设置一个地理区域,当用户进入或离开该区域时,触发相应的事件。可以使用
CLLocationManager
的
startMonitoringForRegion:
方法实现地理围栏功能。
17. 总结与展望
通过本文的介绍,我们了解了Core Location的基本使用方法、技术细节和优化策略。Core Location为开发者提供了一个强大而简单的接口,让我们可以轻松地在应用中添加定位功能。
在未来的开发中,随着定位技术的不断发展,Core Location可能会提供更多的功能和更高的精度。开发者可以根据应用的需求,合理利用Core Location,为用户提供更好的体验。
以下是拓展应用场景的列表:
- 运动记录:记录跑步、骑行等运动的轨迹和距离。
- 地理围栏:设置地理区域,触发相应事件。
- 社交应用:显示附近的好友。
- 旅游应用:提供景点的导航和介绍。
同时,为了更好地理解不同精度级别对电量的影响,我们可以绘制一个简单的图表:
graph LR;
A[kCLLocationAccuracyBest] -->|高电量消耗| B[导航应用];
C[kCLLocationAccuracyNearestTenMeters] -->|中电量消耗| D[附近商家推荐];
E[kCLLocationAccuracyKilometer] -->|低电量消耗| F[天气应用];
总之,Core Location是一个非常实用的框架,掌握其使用方法和优化策略,将有助于开发出更高效、更智能的应用。
Core Location定位使用指南
超级会员免费看
402

被折叠的 条评论
为什么被折叠?



