XestiMonitors 2.12.1

XestiMonitors 2.12.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
已发布上次发布2018年9月
SPM支持 SPM

J. G. Pusey 维护。



  • 作者
  • J. G. Pusey

XestiMonitors

Swift 4.x License Platform

Build Status Code Coverage Documented

CocoaPods Carthage Swift Package Manager

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是可扩展的——您可以轻松创建自己的自定义监视器。有关详细信息,请参阅自定义监视器

参考文档

完整的参考文档可通过Jazzy获得。

需求

  • 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.swiftdependencies 值一样简单。

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 提供了三个监视器类,可以使用这些类来观察系统生成的可访问性事件

Application Monitors

XestiMonitors 提供了七个监控类,可以使用它们观察系统生成的关于应用程序的常见事件

Device Monitors

XestiMonitors 提供了三个监控类,可用于检测设备特性的变更

Screen Monitors

XestiMonitors 提供了四个监控类,可用于检测屏幕相关属性的变化

文本监控

XestiMonitors 提供了四个监控类,可用于检测文本输入模式和内容的变化

其他 UIKit 监控器

此外,XestiMonitors 还提供了九个其他 UIKit 监控器

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还提供了两个其他监视器

自定义监视器

最好的是,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 许可证