测试已测试 | ✓ |
语言语言 | SwiftSwift |
许可证 | MIT |
发布最新发布 | 2016年11月 |
SwiftSwift 版本 | 3.0 |
SPM支持 SPM | ✗ |
由 RxLocationManager 维护。
如果你采用 RP(RxSwift) 模式进行应用程序开发,可能觉得 CLLocationManager 使用起来不方便。RxLocationManager 旨在为 CLLocationManager 创建一个“reactive”界面,这样就无需担心像使视图控制器符合 CLLocationManagerDelegate,这有时感觉不太自然,或者放置 CLLocationManager 实例(例如 AppDelegate)以便轻松引用等问题。所有这些都在 RxLocationManager 类及其静态方法和变量中完成。内部 RxLocationManager 有多个共享的 CLLocationManagerDelegate 实例,并在内存使用和电池寿命方面有效地管理它们。RxLocationManager 并不像 CLLocationManager 那样提供“一站式”类,而是根据它们的相对性将属性和方法分为几个组,例如将位置相关 API 放入 StandardLocationService 类,将航向更新相关 API 放入 HeadingUpdateService 类,将区域监控相关 API 放入 RegionMonitoringService 类(它还包括测距信标功能),并将访问监控相关 API 放入 MonitoringVisitsService,因此使用起来更清晰。
$ git submodule add [email protected]:popduke/RxLocationManager.git
RxLocationManager.xcodeproj
拖动到 Project Navigator项目 > 目标 > 编译阶段 > 链接二进制库
,点击 +
并选择 RxLocationManager [平台]
目标在导入 RxLocationManager 模块时添加以下行
import RxLocationManager
RxLocationManager.enable
.map{
//$0 is Boolean
return $0 ? "enabled" : "disabled"
}
.subscribe(onNext:{
print("Location Service is \($0)")
})
.addDisposableTo(disposeBag)
RxLocationManager.authorizationStatus
.subscribe(onNext:{
//$0 is CLAuthorizationStatus
print("Current authorization status is \($0)")
})
.addDisposableTo(disposeBag)
//ask for WhenInUse authorization
RxLocationManager.requestWhenInUseAuthorization()
//ask for Always authorization
RxLocationManager.requestAlwaysAuthorization()
#if os(iOS) || os(OSX)
RxLocationManager.significantLocationChangeMonitoringAvailable
RxLocationManager.isMonitoringAvailableForClass(regionClass: AnyClass) -> Bool
#endif
#if os(iOS)
RxLocationManager.deferredLocationUpdatesAvailable
RxLocationManager.headingAvailable
RxLocationManager.isRangingAvailable
#endif
StandardLocationService 包含两个主要 Observable:Located 和 Locating,Located 在每次订阅和完成时只报告一个 CLLocation 对象,代表设备的当前确定的地理位置;Locating 在观察时报告一系列的 CLLocation 对象,代表设备的不断变化的位置。多个订阅共享单个底层的 CLLocationManager 对象,RxLocationManager 在第一次订阅时开始位置更新,并在最后一个订阅被丢弃后停止。
// RxLocationManager.Standard is a shared standard location service instance
#if os(iOS) || os(watchOS) || os(tvOS)
RxLocationManager.Standard.located.subscribe(
onNext:{
// the event will only be triggered once to report current determined location of device
print("Current Location is \($0)")
},
onError:{
// in case some error occurred during determining device location, e.g. LocationUnknown
},
onCompleted:{
// completed event will get triggered after location is reported successfully
print("Subscription is Completed")
})
.addDisposableTo(disposeBag)
#endif
#if os(iOS) || os(OSX) || os(watchOS)
//available in watchOS 3.0
RxLocationManager.Standard.locating.subscribe(
onNext:{
// series of events will be delivered during subscription
print("Current Location is \($0)")
},
onError:{
// LocationUnknown error will be ignored, and other errors reported
},
onCompleted:{
// no complete event
})
.addDisposableTo(disposeBag)
#endif
在开始订阅 located 或 locating 之前,您也可以通过以下链式风格的 API 配置标准位置服务实例
RxLocationManager.Standard.distanceFilter(distance: CLLocationDistance) -> StandardLocationService
RxLocationManager.Standard.desiredAccuracy(desiredAccuracy: CLLocationAccuracy) -> StandardLocationService
#if os(iOS)
RxLocationManager.Standard.allowsBackgroundLocationUpdates(allow : Bool) -> StandardLocationService
RxLocationManager.Standard.activityType(type: CLActivityType) -> StandardLocationService
#endif
#if os(iOS)
RxLocationManager.Standard.pausesLocationUpdatesAutomatically(true)
RxLocationManager.Standard.isPaused
.map{
//$0 is Boolean
return $0 ? "Paused" : "Resumed"
}
.subscribe(
onNext:{
print("Location Updating is \($0)")
}
)
.addDisposableTo(disposeBag)
#endif
#if os(iOS)
//Setup deferred location update condition
RxLocationManager.Standard.allowDeferredLocationUpdates(untilTraveled:100, timeout: 120)
//Remove current deferred update condition
RxLocationManager.Standard.disallowDeferredLocationUpdates()
//Observe the event when condition is satisfied or finished with error
RxLocationManager.Standard.deferredUpdateFinished
.map{
//$0 is NSError?
return $0 == nil ? "Finished" : "Finished with error code \($0.code) in \($0.domain)"
}
.subscribe(
onNext:{
error in
print("Location Updating is \($0)")
}
)
.addDisposableTo(disposeBag)
#endif
在某些情况下,您的应用可能需要多个配置不同的标准位置服务,您可以通过从共享实例克隆来创建一个新的实例
var anotherStandardLocationService = RxLocationManager.Standard.clone()
anotherStandardLocationService.distanceFilter(100).desiredAccuracy(50)
SignificantLocationUpdateService 只包含一个 Observable:locating,在观察时会报告一系列的 CLLocation 对象,代表设备执行显著的地理位置变化。多个订阅共享单个底层的 CLLocationManager 对象,RxLocationManager 在第一次订阅时开始监视显著的位置变化,并在最后一个订阅被丢弃后停止。
#if os(iOS) || os(OSX)
// RxLocationManager.SignificantLocation is the shared significant location update service instance
RxLocationManager.SignificantLocation.locating.subscribe(
onNext:{
print("Current Location is \($0)")
},
onError:{
// in case errors
},
onCompleted:{
// no complete event
}
)
.addDisposableTo(disposeBag)
#endif
HeadingUpdateService 只包含一个 Observable:heading,在观察时会报告一系列的 CLHeading 对象,代表设备的航向变化。多个订阅共享单个底层的 CLLocationManager 对象,RxLocationManager 在第一次订阅时开始监视设备航向的变化,并在最后一个订阅被丢弃后停止。
#if os(iOS)
// RxLocationManager.HeadingUpdate is the shared heading update service instance
RxLocationManager.HeadingUpdate.heading.subscribe(
onNext:{
// series of events will be delivered during subscription
print("Current heading is \($0)")
},
onCompleted:{
// no complete event
},
onError:{
// in case errors
}
)
.addDisposableTo(disposeBag)
#endif
在开始订阅航向之前,您还可以通过以下链式风格API配置航向更新服务实例
#if os(iOS)
RxLocationManager.HeadingUpdate.headingFilter(degrees:CLLocationDegrees) -> HeadingUpdateService
RxLocationManager.HeadingUpdate.headingOrientation(degrees:CLDeviceOrientation) -> HeadingUpdateService
RxLocationManager.HeadingUpdate.displayHeadingCalibration(should:Bool) -> HeadingUpdateService
//Use following to methods to start/stop location updating, so that true heading value will be reported
RxLocationManager.HeadingUpdate.startTrueHeading(withParams:(distanceFilter:CLLocationDistance, desiredAccuracy:CLLocationAccuracy))
RxLocationManager.HeadingUpdate.stopTrueHeading()
#endif
#if os(iOS)
RxLocationManager.HeadingUpdate.dismissHeadingCalibrationDisplay()
#endif
在某些情况下,您需要您的应用中不止一个航向更新服务,并且它们的配置不同,您可以通过从共享进行克隆来创建一个新的服务
var anotherHeadingUpdateService = RxLocationManager.HeadingUpdate.clone()
anotherHeadingUpdateService.distanceFilter(100).desiredAccuracy(50)
#if os(iOS) || os(OSX)
// methods to start|stop monitoring regions
RxLocationManager.RegionMonitoring.startMonitoringForRegions(regions: [CLRegion]) -> RegionMonitoringService
RxLocationManager.RegionMonitoring.stopMonitoringForRegions(regions: [CLRegion]) -> RegionMonitoringService
RxLocationManager.RegionMonitoring.stopMonitoringForAllRegions() -> RegionMonitoringService
RxLocationManager.RegionMonitoring.monitoredRegions.subscribe(
onNext:{
//happens no matter when new region is added or existing one gets removed from the monitored regions set
regions in
print("Current monitoring \(regions.count) regions")
}
)
.addDisposableTo(disposeBag)
#endif
#if os(iOS) || os(OSX)
RxLocationManager.RegionMonitoring.entering.subscribe(
onNext:{
region in
print("Device is entering the region: \(region.identifier)")
}
)
.addDisposableTo(disposeBag)
RxLocationManager.RegionMonitoring.exiting.subscribe(
onNext:{
region in
print("Device is leaving the region: \(region.identifier)")
}
)
.addDisposableTo(disposeBag)
#endif
RxLocationManager.RegionMonitoring.requestRegionsState(regions:[CLRegion]) -> RegionMonitoringService
RxLocationManager.RegionMonitoring.determinedRegionState.subscribe(
onNext:{
region, state in
print("the region: \(region.identifier) is in state: \(state.rawValue)")
}
)
.addDisposableTo(disposeBag)
#if os(iOS)
RxLocationManager.RegionMonitoring.startRangingBeaconsInRegion(region: CLBeaconRegion)
RxLocationManager.RegionMonitoring.stopRangingBeaconsInRegion(region: CLBeaconRegion)
#endif
#if os(iOS)
RxLocationManager.RegionMonitoring.ranging.subscribe(
onNext:{
beacons, inRegion in
print("\(beacons.count) beacons ranged in range:\(inRange.identifier)")
}
)
.addDisposableTo(disposeBag)
#endif
#if os(iOS)
RxLocationManager.VisitMonitoring.startMonitoringVisits()
RxLocationManager.VisitMonitoring.stopMonitoringVisits()
#endif
#if os(iOS)
RxLocationManager.VisitMonitoring.visiting.subscribe(
onNext:{
visit in
print("coordinate: \(visit.coordinate.longitude),\(visit.coordinate.latitude)")
}
)
.addDisposableTo(disposeBag)
#endif