XestiMonitors
Overview
XestiMonitors 框架提供了六十多个功能齐全的监视器类,可以直接使用,使您的应用能够轻松检测和响应许多常见的系统生成的事件。
在其他方面,您可以把 XestiMonitors 看作是一种更好的管理最常见的通知(主要在 iOS 和 tvOS 上)的方式。目前, XestiMonitors 提供了围绕几乎所有 UIKit
通知(参见 UIKit Monitors)和许多 Foundation
通知(参见 Foundation Monitors)的“封装”。
XestiMonitors 还提供了一些框架和编程接口的便捷封装,以便使您的应用更容易使用
- 它封装了 Core Location 框架,使您的应用更容易确定设备的地理位置、海拔或朝向;或它与附近 iBeacon 的相对位置。详细信息请参阅 Core Location Monitors。
- 它还封装了 Core Motion 框架,使您的应用可以更容易地从设备获取原始和经过处理的运动测量值。详细信息请参阅 Core Motion Monitors。
- 它封装了
SCNetworkReachability
编程接口,使得您的应用程序可以非常容易地确定目标主机的可达性。有关详细信息,请参阅其他监视器。
在XestiMonitors的未来版本中,将推出针对所有四个平台更多区域的附加监视器!
最后,XestiMonitors是可扩展的——您可以轻松创建自己的自定义监视器。有关详细信息,请参阅自定义监视器。
参考文档
需求
- iOS 9.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+
- Xcode 9.0+
- Swift 4.0+
安装
CocoaPods
CocoaPods是一个用于Cocoa项目的依赖关系管理器。您可以使用以下命令安装它:
$ gem install cocoapods
要使用CocoaPods将XestiMonitors集成到您的Xcode项目中,请在您的Podfile
中指定它:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
target '<Your Target Name>' do
pod 'XestiMonitors'
end
然后,运行以下命令:
$ pod install
Carthage
Carthage是一个分散式依赖关系管理器,它可以构建您的依赖关系并为您提供二进制框架。
您可以使用以下命令使用Homebrew安装Carthage:
$ brew update
$ brew install carthage
要将 XestiMonitors 集成到您的 Xcode 项目中使用 Carthage,请在您的 Cartfile
中指定它。
github "eBardX/XestiMonitors"
然后,运行以下命令:
$ carthage update
最后,将构建的 XestiMonitors.framework
拖入您的 Xcode 项目中。
Swift 包管理器
Swift 包管理器 是一个用于自动化 Swift 代码分发的小工具,且已集成到 Swift 编译器中。它目前处于早期开发阶段,但 XestiMonitors 支持在支持的平台上使用。
一旦您设置了 Swift 包,将 XestiMonitors 添加为依赖项就像将其添加到 Package.swift
的 dependencies
值一样简单。
dependencies: [
.Package(url: "https://github.com/eBardX/XestiMonitors.git")
]
使用方法
所有的监视器类都符合 Monitor 协议,从而您可以为监视器创建数组,可以统一启动或停止——更少的代码!
例如,在一个视图控制器中,您可以懒加载几个监视器,并且还可以懒加载一个包含这些监视器的数组变量
import XestiMonitors
lazy var keyboardMonitor = KeyboardMonitor { [unowned self] in
// do something…
}
lazy var memoryMonitor = MemoryMonitor { [unowned self] in
// do something…
}
lazy var orientationMonitor = OrientationMonitor { [unowned self] in
// do something…
}
lazy var monitors: [Monitor] = [keyboardMonitor,
memoryMonitor,
orientationMonitor]
然后,在 viewWillAppear(_:)
和 viewWillDisappear(_:)
方法中,您只需用一行代码即可启动或停止所有这些监视器
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
monitors.forEach { $0.startMonitoring() }
}
override func viewWillDisappear(_ animated: Bool) {
monitors.forEach { $0.stopMonitoring() }
super.viewWillDisappear(animated)
}
很简单!
Core Location 监视器
XestiMonitors 提供了七个封装 Core Location 框架的监视器类,您可以用来确定设备的位置、高度或方向,或者相对于附近的 iBeacon 的位置。
- BeaconRangingMonitor 用于监视区域以查找对蓝牙低能量信标范围内范围(即相对邻近度)的变化。(iOS)
- HeadingMonitor 用于监视设备当前航向的变化。(iOS)
- LocationAuthorizationMonitor 用于监视应用对其使用位置服务的授权更新。(iOS、macOS、tvOS、watchOS)
- RegionMonitor 用于监视区域状态(显示边界转换)的变化。(iOS、macOS)
- SignificantLocationMonitor 用于监视对设备当前位置的重大变化。(iOS、macOS)
- 使用 StandardLocationMonitor 来监控设备当前位置的变化。 (iOS, macOS, tvOS, watchOS)
- 使用 VisitMonitor 来监控用户停留较长时间的地点。 (iOS)
Core Motion Monitors
XestiMonitors 提供了七种监视类,包装 Core Motion 框架,您可以使用这些类从设备获取原始和经过处理的运动测量值。
- AccelerometerMonitor 用于监控设备的加速度计,以获取三个空间轴上的加速度的周期性原始测量值。 (iOS, watchOS)
- AltimeterMonitor 用于监控设备相对高度的变化。 (iOS, watchOS)
- DeviceMotionMonitor 用于监控设备的加速度计、陀螺仪和磁力计以获取周期性原始测量值,这些测量值随后被处理为设备运动测量值。 (iOS, watchOS)
- GyroscopeMonitor 用于监控设备的陀螺仪,以获取围绕三个空间轴的旋转速率的周期性原始测量值。 (iOS, watchOS)
- MagnetometerMonitor 用于监控设备的磁力计,以获取围绕三个空间轴的磁场周期性原始测量值。 (iOS, watchOS)
- MotionActivityMonitor 用于监控设备的实时和历史运动数据。 (iOS, watchOS)
- PedometerMonitor 用于监控设备的实时和历史步数数据。 (iOS, watchOS)
Foundation Monitors
XestiMonitors 提供了十七种监视器,包装了 Foundation
通知
- BundleClassLoadMonitor 用于监控程序包的动态类加载。 (iOS, macOS, tvOS, watchOS)
- BundleResourceRequestMonitor 用于监控系统以检测可用磁盘空间是否变低,以供按需资源使用。 (iOS, tvOS, watchOS)
- CalendarDayMonitor 用于监控系统日历日的变化。 (iOS, macOS, tvOS, watchOS)
- CurrentLocaleMonitor 用于监控系统用户位置的更改。 (iOS, macOS, tvOS, watchOS)
- ExtensionHostMonitor 用于监视扩展上下文,以检测扩展宿主应用的运行状态变化。(iOS, tvOS, watchOS)
- [HTTPCookiesStorageMonitor][http_cookies_storage_monitor] 实例用于监视 HTTP 钱包存储对象,以检测其接受策略或其饼干的变化。(iOS, macOS, tvOS, watchOS)
- MetadataQueryMonitor 用于监视元数据查询的结果变化。(iOS, macOS, tvOS, watchOS)
- PortMonitor 用于监视端口的验证状态变化。(iOS, macOS, tvOS, watchOS)
- ProcessInfoPowerStateMonitor 用于监视设备电源状态变化(低电量模式启用或禁用)。(iOS, tvOS, watchOS)
- ProcessInfoThermalStateMonitor 用于监视系统温度状态变化。(iOS, macOS, tvOS, watchOS)
- SystemClockMonitor 用于监视系统时钟变化。(iOS, macOS, tvOS, watchOS)
- SystemTimeZoneMonitor 用于监视系统当前使用的时间区变化。(iOS, macOS, tvOS, watchOS)
- UbiquitousKeyValueStoreMonitor 用于监视 iCloud(“无处不在”)键值存储,以检测由于来自 iCloud 的推送数据引起的更改。(iOS, macOS, tvOS)
- UbiquityIdentityMonitor 用于监视系统对 iCloud(“无处不在”)身份的更改。(iOS, macOS, tvOS, watchOS)
- UndoManagerMonitor 用于监视撤销管理器对操作记录的更改。(iOS, macOS, tvOS, watchOS)
- URLCredentialStorageMonitor 用于监视共享 URL 凭据存储对象,以检测其存储的凭证更改。(iOS, macOS, tvOS, watchOS)
- UserDefaultsMonitor 用于监视用户默认设置对象的数据变化。(iOS, macOS, tvOS, watchOS)
UIKit Monitors
XestiMonitors 提供了 numerous monitors wrapping UIKit
notifications.
Accessibility Monitors
XestiMonitors 提供了三个监视器类,可以使用这些类来观察系统生成的可访问性事件
- AccessibilityAnnouncementMonitor 用于监视系统,以检测语音控制完成输出的可访问性公告。(iOS, tvOS)
- AccessibilityElementMonitor 用于监控辅助技术对元素焦点的变更。 (iOS, tvOS)
- AccessibilityStatusMonitor 用于监控系统各种辅助设置状态的变更。 (iOS, tvOS)
Application Monitors
XestiMonitors 提供了七个监控类,可以使用它们观察系统生成的关于应用程序的常见事件
- ApplicationStateMonitor 用于监控应用程序运行时状态的变更。 (iOS, tvOS)
- BackgroundRefreshMonitor 用于监控应用程序在后台下载内容的变更。 (iOS)
- MemoryMonitor 用于监控操作系统对应用程序发送的内存警告。 (iOS, tvOS)
- ProtectedDataMonitor 用于监控对受保护文件可访问性的变更。 (iOS, tvOS)
- ScreenshotMonitor 用于监控屏幕截图。 (iOS, tvOS)
- StatusBarMonitor 用于监控用户界面方向或状态栏框架的变更。 (iOS)
- TimeMonitor 用于监控应用程序发生重大时间变更。 (iOS, tvOS)
Device Monitors
XestiMonitors 提供了三个监控类,可用于检测设备特性的变更
- BatteryMonitor 用于监控设备电池的充电状态和充电级别变更。 (iOS)
- OrientationMonitor 用于监控设备物理方向的变更。 (iOS)
- ProximityMonitor 用于监控设备接近传感器的状态变更。 (iOS)
Screen Monitors
XestiMonitors 提供了四个监控类,可用于检测屏幕相关属性的变化
- ScreenBrightnessMonitor 监控屏幕亮度等级的变化。 (iOS, tvOS)
- ScreenCapturedMonitor 监控屏幕捕获状态的变化。 (iOS, tvOS)
- ScreenConnectionMonitor 监控设备屏幕的连接和断开。 (iOS, tvOS)
- ScreenModeMonitor 监控屏幕当前模式的变化。 (iOS, tvOS)
文本监控
XestiMonitors 提供了四个监控类,可用于检测文本输入模式和内容的变化
- TextFieldTextMonitor 监控文本框文本的变化。 (iOS, tvOS)
- TextInputModeMonitor 监控应答链当前输入模式的变化。 (iOS, tvOS)
- TextStorageMonitor 监控文本存储内容的编辑处理。 (iOS, tvOS)
- TextViewTextMonitor 监控文本视图文本的变化。 (iOS, tvOS)
其他 UIKit 监控器
此外,XestiMonitors 还提供了九个其他 UIKit
监控器
- ContentSizeCategoryMonitor 监控应用偏好内容大小类别变化。 (iOS, tvOS)
- DocumentStateMonitor 监控文档状态的变化。 (iOS)
- FocusMonitor 监控视图层次结构中的当前焦点变化。 (iOS, tvOS)
- KeyboardMonitor 监控键盘的可见性或其框架的变化。 (iOS)
- MenuControllerMonitor 监控编辑菜单的可见性或其框架的变化。 (iOS)
- PasteboardMonitor 监控粘贴板内容的更改或其从应用中移除。 (iOS)
- TableViewSelectionMonitor 监控表格视图选中行的更改。 (iOS, tvOS)
- ViewControllerShowDetailTargetMonitor 用于监视视图中分割视图控制器显示模式的变化。 (iOS, tvOS)
- WindowMonitor 用于监视窗口的可见性或键状态的变化。 (iOS, tvOS)
KeyboardMonitor 特别有用,可以轻松地从您的应用中去除大量的样板代码。以下是通常在自定义视图中处理键盘监视的方式
func keyboardWillHide(_ notification: Notification) {
let userInfo = notification.userInfo
var animationDuration: TimeInterval = 0
if let value = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue {
animationDuration = value
}
constraint.constant = 0
UIView.animate(withDuration: animationDuration) {
self.view.layoutIfNeeded()
}
}
func keyboardWillShow(_ notification: Notification) {
let userInfo = notification.userInfo
var animationDuration: TimeInterval = 0
if let value = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue {
animationDuration = value
}
var frameEnd = CGRect.zero
if let value = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
frameEnd = value
}
constraint.constant = frameEnd.height
UIView.animate(withDuration: animationDuration) {
self.view.layoutIfNeeded()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let nc = NotificationCenter.`default`
nc.addObserver(self, selector: #selector(keyboardWillHide(_:)),
name: .UIKeyboardWillHide, object: nil)
nc.addObserver(self, selector: #selector(keyboardWillShow(_:)),
name: .UIKeyboardWillShow, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.`default`.removeObserver(self)
super.viewWillDisappear(animated)
}
而且这是XestiMonitors使用 KeyboardMonitor 的方式
import XestiMonitors
lazy var keyboardMonitor = KeyboardMonitor { [unowned self] event in
guard let constraint = self?.constraint,
let view = self?.view else { return }
switch event {
case let .willHide(info):
constraint.constant = 0
UIView.animate(withDuration: info.animationDuration) {
view.layoutIfNeeded()
}
case let .willShow(info):
constraint.constant = info.frameEnd.height
UIView.animate(withDuration: info.animationDuration) {
view.layoutIfNeeded()
}
default:
break
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
keyboardMonitor.startMonitoring()
}
override func viewWillDisappear(_ animated: Bool) {
keyboardMonitor.stopMonitoring()
super.viewWillDisappear(animated)
}
你的钱包里有什么?
其他监视器
此外,XestiMonitors还提供了两个其他监视器
- FileSystemObjectMonitor 用于监视文件系统对象的变化。 (iOS, macOS, tvOS, watchOS)
- NetworkReachabilityMonitor 用于监控网络节点名称或地址的可达性变化。 (iOS, macOS, tvOS)
自定义监视器
最好的是,XestiMonitors框架提供了几种轻松创建自定义监视器的方法。
实现监视器协议
你可以创建一个新类,或扩展一个现有的类,以便它遵守 Monitor 协议。您只需要实现 startMonitoring() 和 stopMonitoring() 方法,以及 isMonitoring 属性
import XestiMonitors
extension MegaHoobieWatcher: Monitor {
var isMonitoring: Bool { return watchingForHoobiesCount() > 0 }
func startMonitoring() -> Bool {
guard !isMonitoring else { return }
beginWatchingForHoobies()
}
func stopMonitoring() -> Bool {
guard isMonitoring else { return }
endWatchingForHoobies()
}
}
注意: 在 startMonitoring() 和 stopMonitoring() 中的保护语句防止在监视器状态不正确时启动或停止监视器。这是一种良好的编码实践。
继承BaseMonitor类
通常,您需要创建BaseMonitor的子类。使用这种抽象基类的优点是,基本的防护逻辑会由您来处理。具体来说,BaseMonitor中的startMonitoring()方法在监控器已激活的情况下不会尝试启动监控,stopMonitoring()方法在监控器未激活的情况下不会尝试停止监控。您无需直接实现所需的协议方法和属性,只需覆盖基类的configureMonitor()和cleanupMonitor()方法即可。事实上,您将无法覆盖startMonitoring()和stopMonitoring()方法,或isMonitoring属性——它们在BaseMonitor中被声明为final
。
import XestiMonitors
class GigaHoobieMonitor: BaseMonitor {
let handler: (Float) -> Void
@objc let hoobie: GigaHoobie
private var observation: NSKeyValueObservation?
init(_ hoobie: GigaHoobie, handler: @escaping (Float) -> Void) {
self.handler = handler
self.hoobie = hoobie
}
override func configureMonitor() -> Bool {
super.configureMonitor()
observation = hoobie.observe(\.nefariousActivityLevel) { [unowned self] hoobie, _ in
self.handler(hoobie.nefariousActivityLevel) }
}
override func cleanupMonitor() -> Bool {
observation?.invalidate()
observation = nil
super.cleanupMonitor()
}
}
注意:请务必调用configureMonitor()和cleanupMonitor()的父类实现。
继承BaseNotificationMonitor类
如果您的自定义监控器通过观察通知来确定事件,则应考虑创建BaseNotificationMonitor的子类。在大多数情况下,您只需覆盖addNotificationObservers(_:)方法即可。如果需要在监控器停止时取消通知观察者的额外清理,则还可以覆盖removeNotificationObservers(_:)方法。尽管这个基类继承自BaseMonitor,但您将无法覆盖configureMonitor()和cleanupMonitor()方法——它们在BaseNotificationMonitor中被声明为final
。
import XestiMonitors
class TeraHoobieMonitor: BaseNotificationMonitor {
let handler: (Bool) -> Void
let hoobie: TeraHoobie
init(hoobie: TeraHoobie, queue: OperationQueue = .main,
handler: @escaping (Bool) -> Void) {
self.handler = handler
self.hoobie = hoobie
super.init(queue: queue)
}
override func addNotificationObservers() -> Bool {
super.addNotificationObservers()
observe(.teraHoobieDidChange) { [unowned self] _ in
self.handler(self.hoobie.value) }
}
}
注意:请确保在您的重写中调用超类的addNotificationObservers(_:) 和removeNotificationObservers(_:) 方法。
致谢
J. G. Pusey ([email protected])
许可证
XestiMonitors 适用于MIT 许可证。