在应用程序中使用基于位置的信息是让用户与周围世界保持连接的一个好方法。但是,不正确或不必要的位置使用可能会阻止设备睡眠,保持位置硬件通电,耗尽用户的电池,并造成不良的用户体验。遵循最佳实践,优化位置服务的使用,以提高能效。
有关使用定位服务的详细信息,请参见 Location and Maps Programming Guide
请求快速位置更新
如果您的应用程序只需要快速修复用户的位置,那么最好调用location manager对象的requestLocation方法,如清单14-1所示。这样做会在请求完成后自动停止位置服务,如果不在其他地方使用,则会让位置硬件断电。以这种方式请求的位置更新通过回调传递到locationManager:didUpdateLocations:delegate方法,您必须在应用程序中实现该方法。
清单14-1正式请求单个位置更新
-(void)viewDidLoad {
// Create a location manager object
self.locationManager = [[CLLocationManager alloc] init];
// Set the delegate
self.locationManager.delegate = self;
}
-(void)getQuickLocationUpdate {
// Request location authorization
[self.locationManager requestWhenInUseAuthorization];
// Request a location update
[self.locationManager requestLocation];
// Note: requestLocation may timeout and produce an error if authorization has not yet been granted by the user
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// Process the received location update
}
不使用位置服务时停止这些服务
除了提供转弯方向的导航应用程序外,大多数应用程序不需要一直打开位置服务。只有在需要时才打开位置服务。然后,让它们打开足够长的时间,以便定位并再次关闭它们。除非用户在移动的车辆中,否则当前位置的更改频率不应太高而成为问题。如果需要其他更新,您可以稍后重新启动位置服务。
要停止标准位置更新,请调用位置管理器对象的stopUpdatengLocation方法。见清单14-2。
清单14-2不再需要时停止位置更新
-(void)getLocationUpdate {
// Create a location manager object
self.locationManager = [[CLLocationManager alloc] init];
// Set the delegate
self.locationManager.delegate = self;
// Request location authorization
[self.locationManager requestWhenInUseAuthorization];
// Start location updates
[self.locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// Get a fix on the user's location
...
// Stop location updates
[self.locationManager stopUpdatingLocation];
}
尽可能降低标准位置更新的准确性
标准位置更新允许您通过设置location manager对象的desiredAccuracy属性来指定从几米到几公里的精度,如清单14-3所示。请求比您需要的更高的精度会导致核心位置为额外的硬件供电,并浪费不必要的精度。除非你的应用程序确实需要知道用户在几米之内的位置,否则不要将精度级别设置为“最佳”(kclocationaccuracybest)或最接近的10米(kclocationaccuracynearttenmeters)。另外,请注意,核心位置通常提供比您要求的更准确的数据。例如,当指定精度级别为3公里(kclocationAccuracythreekm)时,您可能会收到100米左右的精度。
默认情况下,iOS设备上的标准位置更新以最佳的精度级别运行。更改这些设置以符合应用程序的要求。否则,你的应用程序将不必要地浪费能源
清单14-3指定位置更新的准确性
-(void)getLocationUpdate {
// Create a location manager object
self.locationManager = [[CLLocationManager alloc] init];
// Set the delegate
self.locationManager.delegate = self;
// Request location authorization
[self.locationManager requestWhenInUseAuthorization];
// Set an accuracy level. The higher, the better for energy.
self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
// Start location updates
[self.locationManager startUpdatingLocation];
}
如果精度与预期不符,则停止位置更新
如果你的应用没有收到预期准确度的更新,你的应用应该检查它正在收到的更新,并确定准确度是在提高还是保持不变。如果精度没有提高,很可能目前无法达到所需的精度水平。在这种情况下,请停止位置更新,稍后再试,这样您的应用程序就不会持续导致位置硬件断电。
在后台接收位置更新时自动暂停并指定活动类型
如果您的iOS应用在后台运行时必须继续监视位置,请在“ Xcode项目”>“功能”窗格中启用后台模式。选中“位置更新”复选框,如图14-1所示。
图14-1在应用程序中启用后台位置更新

在iOS 9和更高版本中,无论部署目标如何,还必须allowsBackgroundLocationUpdates将位置管理器对象的属性设置为
YES
,以接收后台位置更新。默认情况下,此属性为NO
,并且应保持这种状态,直到您的应用积极要求后台位置更新为止。
确保将位置管理器对象的pausesLocationUpdatesAutomatically属性设置YES
为有助于节省电量。
设置activityType
属性以使“核心位置”知道您的应用在给定时间执行的位置活动类型,例如,如果您的应用正在执行健身跟踪或汽车导航。请参阅CLActivityType以获取活动类型列表。
指定这些设置有助于位置管理器确定最合适的时间来执行位置更新。例如,如果系统确定用户不在移动,则可以自动暂停后台位置更新。
参见清单14-4。
重要stopUpdatingLocation当不再需要位置更新时,即使已启用自动暂停,也不要忘记调用位置管理器对象的方法。
-(void)startBackgroundLocationUpdates {
// Create a location manager object
self.locationManager = [[CLLocationManager alloc] init];
// Set the delegate
self.locationManager.delegate = self;
// Request location authorization
[self.locationManager requestWhenInUseAuthorization];
// Set an accuracy level. The higher, the better for energy.
self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
// Enable automatic pausing
self.locationManager.pausesLocationUpdatesAutomatically = YES;
// Specify the type of activity your app is currently performing
self.locationManager.activityType = CLActivityTypeFitness;
// Enable background location updates
self.locationManager.allowsBackgroundLocationUpdates = YES;
// Start location updates
[self.locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// Perform location-based activity
...
// Stop location updates when they aren't needed anymore
[self.locationManager stopUpdatingLocation];
// Disable background location updates when they aren't needed anymore
self.locationManager.allowsBackgroundLocationUpdates = NO;
}
在后台运行时推迟位置更新
在具有GPS硬件的受支持设备上,您可以让位置管理器在您的应用程序在后台运行时推迟位置更新的交付。例如,跟踪用户在远足径上位置的健身应用可以将更新推迟到用户移动一定距离或经过一定时间后再进行。然后,它可以一次处理所有更新。您可以deferredLocationUpdatesAvailable用来确定设备是否支持推迟的位置更新。
要推迟更新,请调用位置管理器对象的allowDeferredLocationUpdatesUntilTraveled:timeout:方法,并将其传递给距离和时间,该方法可能会在接收到下一个位置更新之前经过。通常在locationManager:didUpdateLocations:委托方法中调用此方法,以便在收到延迟的位置更新时在适当时再次延迟。
收到延迟的位置更新时,locationManager:didFinishDeferredUpdatesWithError:也会调用委托方法,您的应用程序可以借此机会来调整行为以进行下一次更新,例如增加或减少延迟距离和时间。参见清单14-5。
清单14-5根据距离和时间延迟后台位置更新
-(void)startHikeLocationUpdates {
// Create a location manager object
self.locationManager = [[CLLocationManager alloc] init];
// Set the delegate
self.locationManager.delegate = self;
// Request location authorization
[self.locationManager requestWhenInUseAuthorization];
// Specify the type of activity your app is currently performing
self.locationManager.activityType = CLActivityTypeFitness;
// Start location updates
[self.locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// Add the new locations to the hike
[self.hike addLocations:locations];
// Defer updates until the user hikes a certain distance or a period of time has passed
if (!self.deferringUpdates) {
CLLocationDistance distance = self.hike.goal - self.hike.distance;
NSTimeInterval time = [self.nextUpdate timeIntervalSinceNow];
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:distance timeout:time];
self.deferringUpdates = YES;
} }
-(void)locationManager:(CLLocationManager *)manager
didFinishDeferredUpdatesWithError:(NSError *)error {
// Stop deferring updates
self.deferringUpdates = NO;
// Adjust for the next goal
}
将位置更新限制为特定区域或位置
某些应用不需要接收连续的位置更新,只需要知道用户何时位于某个位置的特定距离内即可。例如,杂货应用可以在用户靠近商店时显示新的优惠券。有几种核心位置API可以使您的应用程序了解最新情况
注意
下述监视技术仅提供进入和退出通知。要确定收到通知时用户的实际位置,必须调用位置管理器对象的requestLocation:
或startUpdatingLocation:
方法。这些监视技术还要求授权状态为kCLAuthorizationStatusAuthorizedAlways。
区域和信标监控
核心位置提供了两种方法来检测用户进入和离开特定区域。
- 地理区域监视提供了地球上指定位置的出入通知。
- 当用户在发布iBeacon信息的低功耗蓝牙设备范围内时,Beacon监视会提供进入和退出通知。
有关使用这些技术的详细信息,请参阅地区监测和iBeacon显示在位置和地图编程指南。
访问监控使应用程序可以接收用户频繁或长时间访问的特定位置(例如家庭,工作或喜欢的咖啡店)的出入通知。
要开始监视访问,请将代理分配给位置管理器对象并调用其startMonitoringVisits方法。请注意,调用此方法将启用应用程序中的所有访问更新,而不仅仅是当前委托的更新。启用后,访问事件将传递给locationManager:didVisit:委托的方法。如果在传递访问事件时您的应用未运行,则会自动重新启动您的应用。当不再需要访问位置更新时,请致电stopMonitoringVisits,如清单14-6所示。
清单14-6使用访问监视来接收绑定到特定位置的更新
-(void)startVisitMonitoring {
// Create a location manager object
self.locationManager = [[CLLocationManager alloc] init];
// Set the delegate
self.locationManager.delegate = self;
// Request location authorization
[self.locationManager requestAlwaysAuthorization];
// Start monitoring for visits
[self.locationManager startMonitoringVisits];
}
-(void)stopVisitMonitoring {
[self.locationManager stopMonitoringVisits];
}
-(void)locationManager:(CLLocationManager *)manager didVisit:(CLVisit *)visit {
// Perform location-based activity
...
}
仅在万不得已时注册重大更改位置更新
如果GPS级别的精度对您的应用程序不是至关重要的,则您不需要连续跟踪,并且区域或访问监控对于您的应用程序来说就不太合适,则可以使用重大变化位置服务代替标准的位置服务。
重要
区域和访问监视对于大多数用例而言已足够,并且在重大变化的位置更新之前应始终予以考虑。重大变化的位置更新将全天候连续运行,直到您将其停止为止,并且如果未有效利用,则实际上会导致更高的能耗。
要开始重大更改位置更新,请调用startMonitoringSignificantLocationChanges位置管理器对象的方法。完成后,调用stopMonitoringSignificantLocationChanges,如清单14-7所示。
注意
重大更改位置更新要求授权状态为kCLAuthorizationStatusAuthorizedAlways。
清单14-7请求重大更改位置更新
-(void)startSignificantChangeLocationUpdates {
// Create a location manager object
self.locationManager = [[CLLocationManager alloc] init];
// Set the delegate
self.locationManager.delegate = self;
// Request location authorization
[self.locationManager requestAlwaysAuthorization];
// Start significant-change location updates
[self.locationManager startMonitoringSignificantLocationChanges];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
// Perform location-based activity
// Stop significant-change location updates when they aren't needed anymore
[self.locationManager stopMonitoringSignificantLocationChanges];
}
网友评论