HSObserver

Version License Platform

摘要

用于 Swift 的更佳通知和键值观察器。

安装

HSObserver 可通过 CocoaPods 获得。 要安装它,只需将以下行添加到您的 Podfile 中

pod 'HSObserver'

或作为 swift 包安装

观察器自动释放

class Watcher {
    struct Notif {
        static let wave = NSNotification.Name.init("waveNotification")
    }
    

    var waveObserver:HSObserver
    init() {
        waveObserver = HSObserver.init(forName: Watcher.Notif.wave,
                                           activate:true,
                                           using: { (notif) in
            //Do Something
        })
    }
}

与标准观察器不同,当 Watcher 释放时,waveObserver 会完全释放。

(发布 wave 通知后,Watcher 释放后将不会调用 //Do Something 代码)

在主线程上执行

很容易被意外在后台线程上收到的通知所困扰。 在几乎所有情况下 - 你不希望那样!

(如果您愿意,可以为给定的观察器更改此设置 - 但您可能不应该这样做)

如果您使用不指定队列的初始化器(默认设置),则调用块将标记为 @MainActor - 因此应该可以很好地与 swift 异步代码配合使用

观察器可以被激活和停用

    var waveObserver:HSObserver
    init() {
        waveObserver = HSObserver.init(forName: Watcher.Notif.wave,
                                           using: { (notif) in
            //Do Something
        })

        //activate
        waveObserver.activate()

        //deactivate
        waveObserver.deactivate()
    }

注意:请记住,您必须激活观察器才能使其工作。

HSHasObservers 与视图控制器生命周期很好地集成

视图控制器的一个常见模式是在 viewWillAppear 中激活观察器,并在 viewDidDisppear 中停用它们

HSHasObservers 协议添加到任何类,允许您添加一组观察器,并轻松激活或停用它们。

观察器可以手动添加,也可以通过将 .add(to:self) 链接到 HSObserver 来添加

class ViewController: NSViewController, HSHasObservers {

    override func viewDidLoad() {
        super.viewDidLoad()

        //Add manually
        let waveObserver = HSObserver.init(forName: Watcher.Notif.wave,
                                           using: { (notif) in
                                            //Do Something
        })
        self.add(observer: waveObserver)

        //Or by chaining
        HSObserver.init(forName: Watcher.Notif.wave,
                            using: { (notif) in
                                //Do Something
        }).add(to: self)
    }
}

这与视图生命周期配合良好

    override func viewWillAppear() {
        super.viewWillAppear()

        activateObservers()
    }

    override func viewDidDisappear() {
        super.viewDidDisappear()

        deactivateObservers()
    }

添加多个观察器

    let manyThingsObserver = HSObserver.init(forNames: [Watcher.Notif.wave,Watcher.Notif.hello] ,
                                                     activate:true,
                                           using: { (notif) in
                                            //Do Something
        })

指定中心、队列等

    /// Create observer
    ///
    /// - parameter name:  notification name
    /// - parameter obj:   object to observe (default nil)
    /// - parameter queue: queue to run the block on (default main)
    /// - parameter center: notification center (default NotificationCenter.default)
    /// - parameter block: block to run (beware of retain cycles!)
    ///
    /// - returns: unactivated manager. Call activate() to start
    convenience init(forName name: NSNotification.Name,
                     object obj: Any? = nil,
                     queue: OperationQueue? = .main,
                     center newCenter: NotificationCenter = NotificationCenter.default,
                     activate: Bool = false,
                     using block: @escaping (Notification) -> Swift.Void)

HSObservers 允许您跳过默认值。 我们假设

您可以在初始化器中覆盖这些值中的每一个

请注意,Apple 的默认设置是在与发送者相同的队列上调用您的块。 如果您想这样做,只需使用 center = nil

我发现我通常想使用通知来更新 UI - 所以我的默认设置是使用 .main

Brent Simmons 有一篇关于为什么您几乎总是应该使用 .main 的精彩文章

NSNotification.Name 上的便捷功能

直接发布通知

class Watcher {
  struct Notif {
      static let wave = NSNotification.Name.init("waveNotification")
  }
    

  func doPosting() {
      Watcher.Notif.wave.post()
      //or
      Watcher.Notif.wave.post(object:self,userInfo:["Foo":"Bar"])
  }
}

直接从 NotificationCenter 发布时,假定默认通知中心和默认选项(我强烈建议您在相关对象的 Notif 结构中构建您的通知。这使得事情非常容易阅读)

NotificationCenter.post(Watcher.Notif.wave)
//is equivalent to
NotificationCenter.default.post(Watcher.wave,object:nil)

现在有了键值通知

例如,观察 AVPlayerItem 的持续时间

durationObserver = HSKeyPathObserver.init(forKeyPath: "duration",
                                        of: item,
                                        activate:true) {
                                          [weak self](_) in
                                          self?.generateImages()
}

(同样,请记住保留对 durationObserver 的引用,否则它会消失)

作者

ConfusedVorlon, rob@hobbyistsoftware.com

许可

HSNotification 在 MIT 许可下可用。 有关更多信息,请参见 LICENSE 文件。