@@ -12,40 +12,6 @@ import Foundation
1212// possible risk of deadlock. These methods also ensure that
1313// the notifications are always fired on the main thread.
1414extension NotificationCenter {
15-
16- /// Waits until `name`/`object` is posted.
17- public func observeOnce( _ name: Notification . Name , object: Any ? = nil ) async {
18- await withCheckedContinuation { continuation in
19- // Concurrency in this method is nontrivial. There are at least two
20- // relevant race conditions:
21- //
22- // (1) Multiple threads could post a notification at the same time, and
23- // this will trigger multiple callbacks, even if you call `removeObserver`
24- // as quickly as possible. We guard against this with an atomic
25- // compare-and-swap to set the observer to nil.
26- //
27- // (2) When initially registering the observer, it's possible that another
28- // thread could be posting the notifiation at the same time. If the
29- // notification callback happens before we've assigned the initial value to
30- // the atomic observer value, we'll drop that notification. We avoid that
31- // problem by ensuring that the `addObserver` call and assignment of the
32- // observer happen atomically.
33- //
34- // Memory management in this method is also non-trivial. The observer
35- // captured in the block must be set to nil to avoid leaking memory.
36- let observer = AtomicOptional < NSObjectProtocol > ( nil , lock: . init( ) )
37- _ = observer. map { _ in
38- return addObserver ( forName: name, object: object, queue: nil , using: { [ weak self] notification in
39- guard let observer = observer. swap ( nil ) else {
40- return
41- }
42- self ? . removeObserver ( observer)
43- continuation. resume ( returning: ( ) )
44- } )
45- }
46- }
47- }
48-
4915 public func postOnMainThread( _ notification: Notification ) {
5016 DispatchQueue . main. async {
5117 self . post ( notification)
0 commit comments