// // DarwinNotificationName.swift // punchnet // // Created by 安礼成 on 2026/4/3. // import Foundation // MARK: - Darwin Notification Name public struct DarwinNotificationName: RawRepresentable, Hashable { public let rawValue: String public init(rawValue: String) { self.rawValue = rawValue } } // 预定义名称 extension DarwinNotificationName { static let tunnelEventChanged = DarwinNotificationName(rawValue: "com.jihe.punchnetmac.tunnelEventChanged") } // MARK: - Manager public final class SDLNotificationCenter { public static let shared = SDLNotificationCenter() private let center = CFNotificationCenterGetDarwinNotifyCenter() private var observers: [DarwinNotificationName: (DarwinNotificationName) -> Void] = [:] private let lock = NSLock() private init() {} // MARK: - Add Observer public func addObserver(for name: DarwinNotificationName, queue: DispatchQueue = .main, using block: @escaping (DarwinNotificationName) -> Void ) { lock.lock() defer { lock.unlock() } if observers[name] == nil { // 首次注册到 Darwin Center CFNotificationCenterAddObserver( center, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()), { (_, observer, cfName, _, _) in guard let observer, let cfName else { return } let instance = Unmanaged .fromOpaque(observer) .takeUnretainedValue() let name = DarwinNotificationName(rawValue: cfName.rawValue as String) instance.handle(name: name) }, name.rawValue as CFString, nil, .deliverImmediately ) observers[name] = { n in queue.async { block(n) } } } } // MARK: - Remove Observer public func removeObserver(for name: DarwinNotificationName) { lock.lock() defer { lock.unlock() } if observers[name] != nil { CFNotificationCenterRemoveObserver( center, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()), CFNotificationName(name.rawValue as CFString), nil ) } observers.removeValue(forKey: name) } // MARK: - Post public func post(_ name: DarwinNotificationName) { CFNotificationCenterPostNotification( center, CFNotificationName(name.rawValue as CFString), nil, nil, true ) } // MARK: - Handle private func handle(name: DarwinNotificationName) { lock.lock() let block = observers[name] lock.unlock() block?(name) } }