DarwinNotificationCenter.swift 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. //
  2. // DarwinNotificationCenter.swift
  3. // Broadcast Extension
  4. //
  5. // Created by Alex-Dan Bumbu on 23/03/2021.
  6. // Copyright © 2021 8x8, Inc. All rights reserved.
  7. //
  8. // From https://github.com/jitsi/jitsi-meet-sdk-samples (Apache 2.0 license)
  9. // SPDX-FileCopyrightText: 2021 Alex-Dan Bumbu, 8x8, Inc. All rights reserved.
  10. // SPDX-License-Identifier: Apache-2.0
  11. import Foundation
  12. @objcMembers public class DarwinNotificationCenter: NSObject {
  13. static let shared = DarwinNotificationCenter()
  14. static let broadcastStartedNotification = "TalkiOS_BroadcastStarted"
  15. static let broadcastStoppedNotification = "TalkiOS_BroadcastStopped"
  16. private let notificationCenter: CFNotificationCenter
  17. internal var handlers: [String: [AnyHashable: () -> Void]] = [:]
  18. override init() {
  19. notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
  20. }
  21. func postNotification(_ name: String) {
  22. CFNotificationCenterPostNotification(notificationCenter, CFNotificationName(rawValue: name as CFString), nil, nil, true)
  23. }
  24. func addHandler(notificationName: String, owner: AnyHashable, completionBlock: @escaping () -> Void) {
  25. // When there are already handlers, we just add our own here
  26. if handlers[notificationName] != nil {
  27. handlers[notificationName]?[owner] = completionBlock
  28. return
  29. }
  30. // No handler for this notification -> setup a new darwin observer for that notification
  31. handlers[notificationName] = [owner: completionBlock]
  32. // see: https://stackoverflow.com/a/33262376
  33. let callback: CFNotificationCallback = { _, observer, name, _, _ in
  34. if let observer, let name {
  35. // Extract pointer to `self` from void pointer:
  36. let mySelf = Unmanaged<DarwinNotificationCenter>.fromOpaque(observer).takeUnretainedValue()
  37. if let handlers = mySelf.handlers[name.rawValue as String] {
  38. for handler in handlers {
  39. handler.value()
  40. }
  41. }
  42. }
  43. }
  44. let observer = Unmanaged.passUnretained(self).toOpaque()
  45. CFNotificationCenterAddObserver(self.notificationCenter, observer, callback, notificationName as CFString, nil, .coalesce)
  46. }
  47. func removeHandler(notificationName: String, owner: AnyHashable) {
  48. guard handlers[notificationName] != nil else { return }
  49. // Remove the handler for the specified owner
  50. handlers[notificationName]!.removeValue(forKey: owner)
  51. // There are still other handlers registered for this notification, keep the darwin center observer
  52. if !handlers[notificationName]!.isEmpty {
  53. return
  54. }
  55. // No handlers registered for that notification anymore, remove the observer from darwin center
  56. handlers.removeValue(forKey: notificationName)
  57. let observer = Unmanaged.passUnretained(self).toOpaque()
  58. let name = CFNotificationName(rawValue: notificationName as CFString)
  59. CFNotificationCenterRemoveObserver(notificationCenter, observer, name, nil)
  60. }
  61. }