MMPReactiveCoreLocation 是一个用于 CoreLocation 和 iBeacon 的响应式库,与 ReactiveCocoa 一起使用。
重要提示
特性
尽管实现了大多数 CoreLocation 服务,但一些服务尚未测试,应被视为 alpha 质量。此处记录的功能已测试且应能正常工作
要使用智能默认设置订阅位置流,最简单的方法是调用 locations
方法来获取信号
// import the header
#import <MMPReactiveCoreLocation/MMPReactiveCoreLocation.h>
// build service, subscribe to 'locations' signal
[[[MMPReactiveCoreLocation service]
locations]
subscribeNext:^(CLLocation *location) {
NSLog(@"[INFO] received location: %@", location);
}];
在应用程序的多个地方调用此确切的代码 不会 产生多个 CLLocationManager
+CLLocationManagerDelegate
集合。库将根据定义服务时指定的设置管理、启动和停止共享的 CLLocationManager
+CLLocationManagerDelegate
实例。例如,以下代码 将 创建一个新的 CLLocationManager
+CLLocationManagerDelegate
集合,因为它需要一个自定义的 activityType
[[[[MMPReactiveCoreLocation service]
activityType:CLActivityTypeFitness]
locations]
subscribeNext:^(CLLocation *location) {
NSLog(@"[INFO] received location: %@", location);
}];
如果您不需要持续的位置更新流,可以使用 location
(注意没有复数 s
)获取最新位置一次,然后库将自动停止 CLLocationManager 并清理资源
// one-time location
[[[MMPReactiveCoreLocation service]
location]
subscribeNext:^(CLLocation *location) {
NSLog(@"[INFO] received single location: %@", location);
}];
有一种针对单个位置订阅的特定选项,称为 timeout
。此选项可以用来指定在等待位置多长时间后信号应放弃(例如,在地下等情况下当前没有可用位置时)。这对于应用程序即使在没有位置信息的情况下也应该继续运行尤其有用。服务超时将在以下示例中产生信号错误:
// one-time location with 5 sec. timeout
[[[[MMPReactiveCoreLocation service]
timeout:5.0]
location]
subscribeNext:^(CLLocation *location) {
NSLog(@"[INFO] received single location: %@", location);
}
error:^(NSError *error) {
NSLog(@"[ERROR] error getting location: %@", error);
}
completed:^{
NSLog(@"[INFO] single location signal completed.");
}];
对于重要变更更新,请使用 significantLocationChanges
信号。
// build service, subscribe to 'significantLocationChanges' signal
[[[MMPReactiveCoreLocation service]
significantLocationChanges]
subscribeNext:^(CLLocation *location) {
NSLog(@"[INFO] received location: %@", location);
}];
就像使用 locations
进行持续更新和 location
进行单个更新一样,使用 significantLocationChanges
进行持续的重要位置变更更新,仅使用 significantLocationChange
进行单个重要位置变更。
对于区域监控,使用 region
添加要监控的区域,并使用 regionEvents
获取信号。
// build service, add 2 regions to monitor, subscribe to region events
[[[[[MMPReactiveCoreLocation service]
region:region1]
region:region2]
regionEvents]
subscribeNext:^(MMPRegionEvent *regionEvent) {
NSLog(@"[INFO] received event: %ld for region: %@", regionEvent.type, regionEvent.region.identifier);
}];
您还可以多次调用 region
方法来定义多个要监控的区域。有关可获得哪些区域事件的更多详细信息,请参阅 MMPRegionEventType
。
要停止任何信号并自动清理底层位置管理器和服务请求,只需使用 stop
方法。
self.service = [MMPReactiveCoreLocation service];
// use 'stop' to tell the service that it should stop the subscription. Underlying location manager (CLLocationManager)
// will automatically be stopped and cleaned up if there are no other subscriber.
[self.service stop];
请注意,如果有多个终端用户使用共享底层位置管理器(即以完全相同的设置构建和配置的服务)的信号,则停止一个终端用户不一定停止位置管理器。
位置信号默认设置如下:
locations
的授权类型是“当使用时”,对于 significantLocationChanges
和 regionEvents
的授权类型是“始终”。如果您需要除默认设置之外的其他设置,则可以链式调用以下方法来设置您想要定制的值
distanceFilter
用于设置距离过滤。desiredAccuracy
用于设置所需精度。activityType
用于设置活动类型。pauseLocationUpdatesAutomatically
或 pauseLocationUpdatesManually
以设置自动或手动更新位置暂停。以下是示例代码,演示在订阅 SIGNAL 之前如何自定义位置管理器设置:
MMPReactiveCoreLocation *service = [MMPReactiveCoreLocation service];
RACSignal *locations = [[[[service distanceFilter:kCLDistanceFilterNone]
desiredAccuracy:kCLLocationAccuracyBestForNavigation]
activityType:CLActivityTypeFitness]
locations];
请参阅头文件以获取更多设置选项。
// handling authorization status change
[[service authorizationStatus] subscribeNext:^(NSNumber *statusNumber) {
CLAuthorizationStatus status = [statusNumber intValue];
switch (status) {
case kCLAuthorizationStatusNotDetermined:
NSLog(@"[INFO] Status changed: kCLAuthorizationStatusNotDetermined");
break;
case kCLAuthorizationStatusRestricted:
NSLog(@"[INFO] Status changed: kCLAuthorizationStatusRestricted");
break;
case kCLAuthorizationStatusDenied:
NSLog(@"[INFO] Status changed: kCLAuthorizationStatusDenied");
break;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
case kCLAuthorizationStatusAuthorizedAlways:
NSLog(@"[INFO] Status changed: kCLAuthorizationStatusAuthorizedAlways");
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(@"[INFO] Status changed: kCLAuthorizationStatusAuthorizedWhenInUse");
break;
#else
case kCLAuthorizationStatusAuthorized:
NSLog(@"[INFO] Status changed: kCLAuthorizationStatusAuthorized");
break;
#endif
default:
break;
}
}];
// handling errors
[[service errors] subscribeNext:^(NSError *error) {
NSLog(@"[ERROR] Location service error: %@", error);
}];
当您需要手动发送授权请求时,例如在使用 MKMapView
并只需要在设置 showsUserLocation
之前发送请求时,可以使用返回状态事件生成信号(与 authorizationStatus
信号相同)的 requestAuthorization
方法。
[[[[MMPReactiveCoreLocation service]
authorizeAlways]
requestAuthorization]
subscribeNext:^(NSNumber *statusNumber) {
CLAuthorizationStatus status = [statusNumber intValue];
switch (status) {
case kCLAuthorizationStatusAuthorizedAlways:
case kCLAuthorizationStatusAuthorizedWhenInUse:
_mapView.showsUserLocation = YES;
break;
case kCLAuthorizationStatusAuthorized:
_mapView.showsUserLocation = YES;
break;
default:
break;
}
}];
大部分的CLLocationManager功能,包括iBeacon、访客监控、航向更新等,已实现,但尚未进行充分的测试,因此可能存在bug。我计划将其用于实际项目中,因此应积极维护。欢迎贡献力量。
随着我对bug的修复和测试的编写,我会编写更多的使用示例和文档。在此期间,如果您对该库如何实现某些CLLocationManager使用模式有任何疑问,请随时联系我或创建问题。
MMPReactiveCoreLocation由Mamad Purbo维护。
MMPReactiveCoreLocation采用MIT许可证。有关更多信息,请参阅LICENSE文件。