|
7 | 7 | // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
8 | 8 | //
|
9 | 9 |
|
| 10 | +@_spi(SwiftCorelibsFoundation) import FoundationEssentials |
| 11 | + |
10 | 12 | @available(*, unavailable)
|
11 | 13 | extension NSNotification : @unchecked Sendable { }
|
12 | 14 |
|
@@ -87,116 +89,67 @@ open class NSNotification: NSObject, NSCopying, NSCoding {
|
87 | 89 |
|
88 | 90 | #if canImport(Dispatch)
|
89 | 91 |
|
90 |
| -private class NSNotificationReceiver : NSObject { |
91 |
| - fileprivate var name: Notification.Name? |
92 |
| - fileprivate var block: (@Sendable (Notification) -> Void)? |
93 |
| - fileprivate var sender: AnyObject? |
94 |
| - fileprivate var queue: OperationQueue? |
95 |
| -} |
96 |
| - |
97 |
| -private let _defaultCenter: NotificationCenter = NotificationCenter() |
98 |
| - |
99 |
| -open class NotificationCenter: NSObject, @unchecked Sendable { |
100 |
| - private lazy var _nilIdentifier: ObjectIdentifier = ObjectIdentifier(_observersLock) |
101 |
| - private lazy var _nilHashable: AnyHashable = AnyHashable(_nilIdentifier) |
102 |
| - |
103 |
| - private var _observers: [AnyHashable /* Notification.Name */ : [ObjectIdentifier /* object */ : [ObjectIdentifier /* notification receiver */ : NSNotificationReceiver]]] |
104 |
| - private let _observersLock = NSLock() |
105 |
| - |
106 |
| - public required override init() { |
107 |
| - _observers = [AnyHashable: [ObjectIdentifier: [ObjectIdentifier: NSNotificationReceiver]]]() |
| 92 | +extension NotificationCenter { |
| 93 | + public func post(_ notification: Notification) { |
| 94 | + _post(notification.name.rawValue, subject: notification.object, message: notification) |
108 | 95 | }
|
109 |
| - |
110 |
| - open class var `default`: NotificationCenter { |
111 |
| - return _defaultCenter |
112 |
| - } |
113 |
| - |
114 |
| - open func post(_ notification: Notification) { |
115 |
| - let notificationNameIdentifier: AnyHashable = AnyHashable(notification.name) |
116 |
| - let senderIdentifier: ObjectIdentifier? = notification.object.map({ ObjectIdentifier(__SwiftValue.store($0)) }) |
117 |
| - |
118 | 96 |
|
119 |
| - let sendTo: [Dictionary<ObjectIdentifier, NSNotificationReceiver>.Values] = _observersLock.synchronized({ |
120 |
| - var retVal = [Dictionary<ObjectIdentifier, NSNotificationReceiver>.Values]() |
121 |
| - (_observers[_nilHashable]?[_nilIdentifier]?.values).map({ retVal.append($0) }) |
122 |
| - senderIdentifier.flatMap({ _observers[_nilHashable]?[$0]?.values }).map({ retVal.append($0) }) |
123 |
| - (_observers[notificationNameIdentifier]?[_nilIdentifier]?.values).map({ retVal.append($0) }) |
124 |
| - senderIdentifier.flatMap({ _observers[notificationNameIdentifier]?[$0]?.values}).map({ retVal.append($0) }) |
125 |
| - |
126 |
| - return retVal |
127 |
| - }) |
128 |
| - |
129 |
| - sendTo.forEach { observers in |
130 |
| - observers.forEach { observer in |
131 |
| - guard let block = observer.block else { |
132 |
| - return |
133 |
| - } |
134 |
| - |
135 |
| - if let queue = observer.queue, queue != OperationQueue.current { |
136 |
| - // Not entirely safe, but maintained for compatibility |
137 |
| - nonisolated(unsafe) let unsafeNotification = notification |
138 |
| - queue.addOperation { block(unsafeNotification) } |
139 |
| - queue.waitUntilAllOperationsAreFinished() |
140 |
| - } else { |
141 |
| - block(notification) |
142 |
| - } |
143 |
| - } |
144 |
| - } |
145 |
| - } |
146 |
| - |
147 |
| - open func post(name aName: NSNotification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]? = nil) { |
148 |
| - let notification = Notification(name: aName, object: anObject, userInfo: aUserInfo) |
149 |
| - post(notification) |
| 97 | + public func post(name aName: NSNotification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]? = nil) { |
| 98 | + post(Notification(name: aName, object: anObject, userInfo: aUserInfo)) |
150 | 99 | }
|
151 | 100 |
|
152 |
| - open func removeObserver(_ observer: Any) { |
| 101 | + public func removeObserver(_ observer: Any) { |
153 | 102 | removeObserver(observer, name: nil, object: nil)
|
154 | 103 | }
|
155 | 104 |
|
156 |
| - open func removeObserver(_ observer: Any, name aName: NSNotification.Name?, object: Any?) { |
157 |
| - guard let observer = observer as? NSNotificationReceiver, |
| 105 | + public func removeObserver(_ observer: Any, name aName: NSNotification.Name?, object: Any?) { |
| 106 | + let objectId = object != nil ? object.map { ObjectIdentifier($0 as AnyObject) } : nil |
| 107 | + |
| 108 | + guard let observer = observer as? _NSNotificationObserverToken, |
158 | 109 | // These 2 parameters would only be useful for removing notifications added by `addObserver:selector:name:object:`
|
159 |
| - aName == nil || observer.name == aName, |
160 |
| - object == nil || observer.sender === __SwiftValue.store(object) |
| 110 | + aName == nil || observer.token.name == aName?.rawValue, |
| 111 | + objectId == nil || observer.token.objectId == objectId |
161 | 112 | else {
|
162 | 113 | return
|
163 | 114 | }
|
164 |
| - |
165 |
| - let notificationNameIdentifier: AnyHashable = observer.name.map { AnyHashable($0) } ?? _nilHashable |
166 |
| - let senderIdentifier: ObjectIdentifier = observer.sender.map { ObjectIdentifier($0) } ?? _nilIdentifier |
167 |
| - let receiverIdentifier: ObjectIdentifier = ObjectIdentifier(observer) |
168 | 115 |
|
169 |
| - _observersLock.synchronized({ |
170 |
| - _observers[notificationNameIdentifier]?[senderIdentifier]?.removeValue(forKey: receiverIdentifier) |
171 |
| - if _observers[notificationNameIdentifier]?[senderIdentifier]?.count == 0 { |
172 |
| - _observers[notificationNameIdentifier]?.removeValue(forKey: senderIdentifier) |
173 |
| - } |
174 |
| - }) |
| 116 | + _removeObserver(observer.token) |
175 | 117 | }
|
176 | 118 |
|
177 | 119 | @available(*, unavailable, renamed: "addObserver(forName:object:queue:using:)")
|
178 |
| - open func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, usingBlock block: @escaping (Notification) -> Void) -> NSObjectProtocol { |
| 120 | + public func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, usingBlock block: @escaping (Notification) -> Void) -> NSObjectProtocol { |
179 | 121 | fatalError()
|
180 | 122 | }
|
181 | 123 |
|
182 |
| - open func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @Sendable @escaping (Notification) -> Void) -> NSObjectProtocol { |
183 |
| - let newObserver = NSNotificationReceiver() |
184 |
| - newObserver.name = name |
185 |
| - newObserver.block = block |
186 |
| - newObserver.sender = __SwiftValue.store(obj) |
187 |
| - newObserver.queue = queue |
188 |
| - |
189 |
| - let notificationNameIdentifier: AnyHashable = name.map({ AnyHashable($0) }) ?? _nilHashable |
190 |
| - let senderIdentifier: ObjectIdentifier = newObserver.sender.map({ ObjectIdentifier($0) }) ?? _nilIdentifier |
191 |
| - let receiverIdentifier: ObjectIdentifier = ObjectIdentifier(newObserver) |
| 124 | + public func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @Sendable @escaping (Notification) -> Void) -> NSObjectProtocol { |
| 125 | + if let queue = queue { |
| 126 | + return _NSNotificationObserverToken(token: _addObserver(name?.rawValue, object: obj) { [weak queue] (notification: Notification) in |
| 127 | + if let queue = queue { |
| 128 | + if queue != OperationQueue.current { |
| 129 | + // Not entirely safe, but maintained for compatibility |
| 130 | + nonisolated(unsafe) let notification = notification |
| 131 | + queue.addOperation { block(notification) } |
| 132 | + queue.waitUntilAllOperationsAreFinished() |
| 133 | + } else { |
| 134 | + block(notification) |
| 135 | + } |
| 136 | + } |
| 137 | + }) |
| 138 | + } else { |
| 139 | + return _NSNotificationObserverToken(token: _addObserver(name?.rawValue, object: obj, using: block)) |
| 140 | + } |
| 141 | + } |
| 142 | +} |
192 | 143 |
|
193 |
| - _observersLock.synchronized({ |
194 |
| - _observers[notificationNameIdentifier, default: [:]][senderIdentifier, default: [:]][receiverIdentifier] = newObserver |
195 |
| - }) |
| 144 | +extension NotificationCenter { |
| 145 | + // Provides NSObjectProtocol conformance for addObserver() |
| 146 | + final class _NSNotificationObserverToken: NSObject { |
| 147 | + internal let token: NotificationCenter._NotificationObserverToken |
196 | 148 |
|
197 |
| - return newObserver |
| 149 | + init(token: NotificationCenter._NotificationObserverToken) { |
| 150 | + self.token = token |
| 151 | + } |
198 | 152 | }
|
199 |
| - |
200 | 153 | }
|
201 | 154 |
|
202 | 155 | #endif // canImport(Dispatch)
|
0 commit comments