XestiMonitors一个采用Swift编写的可扩展监测框架

网友投稿 476 2022-10-29

XestiMonitors一个采用Swift编写的可扩展监测框架

XestiMonitors一个采用Swift编写的可扩展监测框架

XestiMonitors

OverviewReference DocumentationRequirementsInstallationUsageApplication MonitorsDevice MonitorsMotion MonitorsAccessibility MonitorsOther MonitorsCustom Monitors CreditsLicense

Overview

The XestiMonitors framework provides nearly two dozen fully-functional monitor classes right out of the box that make it easy for your app to detect and respond to many common system-generated events.

Among other things, you can think of XestiMonitors as a better way to manage the most common notifications (primarily on iOS). At present, XestiMonitors provides “wrappers” around many UIKit notifications:

Accessibility-relatedUIAccessibilityAnnouncementDidFinishUIAccessibilityAssistiveTouchStatusDidChangeUIAccessibilityBoldTextStatusDidChangeUIAccessibilityClosedCaptioningStatusDidChangeUIAccessibilityDarkerSystemColorsStatusDidChangeUIAccessibilityElementFocusedUIAccessibilityGrayscaleStatusDidChangeUIAccessibilityGuidedAccessStatusDidChangeUIAccessibilityHearingDevicePairedEarDidChangeUIAccessibilityInvertColorsStatusDidChangeUIAccessibilityMonoAudioStatusDidChangeUIAccessibilityReduceMotionStatusDidChangeUIAccessibilityReduceTransparencyStatusDidChangeUIAccessibilityShakeToUndoDidChangeUIAccessibilitySpeakScreenStatusDidChangeUIAccessibilitySpeakSelectionStatusDidChangeUIAccessibilitySwitchControlStatusDidChangeUIAccessibilityVoiceOverStatusDidChange See Accessibility Monitors for details. Application-relatedUIApplicationBackgroundRefreshStatusDidChangeUIApplicationDidBecomeActiveUIApplicationDidChangeStatusBarFrameUIApplicationDidChangeStatusBarOrientationUIApplicationDidEnterBackgroundUIApplicationDidFinishLaunchingUIApplicationDidReceiveMemoryWarningUIApplicationProtectedDataDidBecomeAvailableUIApplicationProtectedDataWillBecomeUnavailableUIApplicationSignificantTimeChangeUIApplicationUserDidTakeScreenshotUIApplicationWillChangeStatusBarFrameUIApplicationWillChangeStatusBarOrientationUIApplicationWillEnterForegroundUIApplicationWillResignActiveUIApplicationWillTerminate See Application Monitors for details. Device-relatedUIDeviceBatteryLevelDidChangeUIDeviceBatteryStateDidChangeUIDeviceOrientationDidChangeUIDeviceProximityStateDidChange See Device Monitors for details. MiscellaneousUIDocumentStateChangedUIKeyboardDidChangeFrameUIKeyboardDidHideUIKeyboardDidShowUIKeyboardWillChangeFrameUIKeyboardWillHideUIKeyboardWillShow See Other Monitors for details.

XestiMonitors also provides a “wrapper” around the Core Motion framework to make it easier for your app to obtain both raw and processed motion measurements from the device. See Motion Monitors for details.

XestiMonitors also provides a “wrapper” around SCNetworkReachability to make it super easy for your app to determine the reachability of a target host. See Other Monitors for details.

Additional monitors targeting more parts of all four platforms will be rolled out in future releases of XestiMonitors!

Finally, XestiMonitors is extensible—you can easily create your own custom monitors. See Custom Monitors for details.

Reference Documentation

Full reference documentation is available courtesy of Jazzy.

Requirements

iOS 9.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+Xcode 9.0+Swift 4.0+

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

To integrate XestiMonitors into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'platform :ios, '9.0'use_frameworks!target '' do pod 'XestiMonitors'end

Then, run the following command:

$ pod install

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update$ brew install carthage

To integrate XestiMonitors into your Xcode project using Carthage, specify it in your Cartfile:

github "eBardX/XestiMonitors"

Run carthage update to build the framework and drag the built XestiMonitors.framework into your Xcode project.

Swift Package Manager

The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler. It is in early development, but XestiMonitors does support its use on supported platforms.

Once you have your Swift package set up, adding XestiMonitors as a dependency is as easy as adding it to the dependencies value of your Package.swift.

dependencies: [ .Package(url: "https://github.com/eBardX/XestiMonitors.git")]

Usage

All monitor classes conform to the Monitor protocol, thus enabling you to create arrays of monitors that can be started or stopped uniformly—fewer lines of code!

For example, in a view controller, you can lazily instantiate several monitors and, in addition, lazily instantiate an array variable containing these monitors:

import XestiMonitorslazy 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] = [self.keyboardMonitor, self.memoryMonitor, self.orientationMonitor]

Then, in the viewWillAppear(_:) and viewWillDisappear(_:) methods, you can simply start or stop all these monitors with a single line of code:

override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) monitors.forEach { $0.startMonitoring() }}override func viewWillDisappear(_ animated: Bool) { monitors.forEach { $0.stopMonitoring() } super.viewWillDisappear(animated)}

Easy peasy!

Application Monitors

XestiMonitors provides seven monitor classes that you can use to observe common events generated by the system about the app:

ApplicationStateMonitor to monitor the app for changes to its runtime state. (iOS, tvOS)BackgroundRefreshMonitor to monitor the app for changes to its status for downloading content in the background. (iOS)MemoryMonitor to monitor the app for memory warnings from the operating system. (iOS, tvOS)ProtectedDataMonitor to monitor the app for changes to the accessibility of protected files. (iOS, tvOS)ScreenshotMonitor to monitor the app for screenshots. (iOS, tvOS)StatusBarMonitor to monitor the app for changes to the orientation of its user interface or to the frame of the status bar. (iOS)TimeMonitor to monitor the app for significant changes in time. (iOS, tvOS)

Device Monitors

XestiMonitors provides three monitor classes that you can use to detect changes in the characteristics of the device:

BatteryMonitor to monitor the device for changes to the charge state and charge level of its battery. (iOS)OrientationMonitor to monitor the device for changes to its physical orientation. (iOS)ProximityMonitor to monitor the device for changes to the state of its proximity sensor. (iOS)

Motion Monitors

XestiMonitors provides seven monitor classes that you can use to obtain raw and processed motion measurements from the device:

AccelerometerMonitor to monitor the device’s accelerometer for periodic raw measurements of the acceleration along the three spatial axes. (iOS, watchOS)AltimeterMonitor to monitor the device for changes in relative altitude. (iOS, watchOS)DeviceMotionMonitor to monitor the device’s accelerometer, gyroscope, and magnetometer for periodic raw measurements which are processed into device motion measurements. (iOS, watchOS)GyroscopeMonitor to monitor the device’s gyroscope for periodic raw measurements of the rotation rate around the three spatial axes. (iOS, watchOS)MagnetometerMonitor to monitor the device’s magnetometer for periodic raw measurements of the magnetic field around the three spatial axes. (iOS, watchOS)MotionActivityMonitor to monitor the device for live and historic motion data. (iOS, watchOS)PedometerMonitor to monitor the device for live and historic walking data. (iOS, watchOS)

Accessibility Monitors

XestiMonitors provides three monitor classes that you can use to observe accessibility events generated by the system:

AccessibilityAnnouncementMonitor to monitor the system for accessibility announcements that VoiceOver has finished outputting. (iOS, tvOS)AccessibilityElementMonitor to monitor the system for changes to element focus by an assistive technology. (iOS, tvOS)AccessibilityStatusMonitor to monitor the system for changes to the status of various accessibility settings. (iOS, tvOS)

Other Monitors

In addition, XestiMonitors provides three other monitors:

DocumentStateMonitor to monitor a document for changes to its state. (iOS)FileSystemObjectMonitor to monitor a file-system object for changes. (iOS, macOS, tvOS, watchOS)KeyboardMonitor to monitor the keyboard for changes to its visibility or to its frame. (iOS)NetworkReachabilityMonitor to monitor a network node name or address for changes to its reachability. (iOS, macOS, tvOS)

KeyboardMonitor is especially handy in removing lots of boilerplate code from your app. This is how keyboard monitoring is typically handled in a custom view controller:

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)}

And this is the XestiMonitors way using KeyboardMonitor:

import XestiMonitorslazy 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)}

What’s in your wallet?

Custom Monitors

Best of all, the XestiMonitors framework provides several ways to create your own custom monitors quite easily.

Implementing the Monitor Protocol

You can create a new class, or extend an existing class, that conforms to the Monitor protocol. You need only implement the startMonitoring() and stopMonitoring() methods, as well as the isMonitoring property:

import XestiMonitorsextension MegaHoobieWatcher: Monitor { var isMonitoring: Bool { return watchingForHoobiesCount() > 0 } func startMonitoring() -> Bool { guard !isMonitoring else { return } beginWatchingForHoobies() } func stopMonitoring() -> Bool { guard isMonitoring else { return } endWatchingForHoobies() }}

Note: The guard statements in both startMonitoring() and stopMonitoring() protect against starting or stopping the monitor if it is in the incorrect state. This is considered good coding practice.

Subclassing the BaseMonitor Class

Typically, you will want to create a subclass of BaseMonitor. The advantage of using this abstract base class is that the basic guard logic is taken care of for you. Specifically, the startMonitoring() method does not attempt to start the monitor if it is already active, and the stopMonitoring() method does not attempt to stop the monitor if it is not active. Instead of directly implementing the required protocol methods and properties, you need only override the configureMonitor() and cleanupMonitor() methods of this base class. In fact, you will not be able to override the startMonitoring() and stopMonitoring() methods or the isMonitoring property—they are declared final in BaseMonitor.

import XestiMonitorsclass 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() }}

Note: Be sure to invoke the superclass implementations of both configureMonitor() and cleanupMonitor().

Subclassing the BaseNotificationMonitor Class

If your custom monitor determines events by observing notifications, you should consider creating a subclass of BaseNotificationMonitor instead. In most cases you need only override the addNotificationObservers(_:) method. You can also override the removeNotificationObservers(_:) method if you require extra cleanup when the notification observers are removed upon stopping the monitor. Although this base class inherits from BaseMonitor, you will not be able to override the configureMonitor() and cleanupMonitor() methods—they are declared final in BaseNotificationMonitor.

import XestiMonitorsclass 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) } }}

Note: Be sure to invoke the superclass implementations of both addNotificationObservers(_:) and removeNotificationObservers(_:) in your overrides.

Credits

J. G. Pusey (ebardx@gmail.com)

License

XestiMonitors is available under the MIT license.

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:集合之HashSet
下一篇:Ktor- 构建异步服务器和客户端的 Kotlin 框架
相关文章

 发表评论

暂时没有评论,来抢沙发吧~