@@ -2,6 +2,30 @@ public import Foundation
22
33extension KeyPath : @unchecked @retroactive Sendable where Value: Sendable { }
44
5+ public extension NSObjectProtocol where Self: NSObject {
6+ /// Returns an `AsyncSequence` of `Value`s for all changes to the given key path on this object.
7+ ///
8+ /// - Parameters:
9+ /// - keyPath: The key path to observe on this object. The value must be `Sendable`.
10+ /// - options: KVO options to use for observation. Defaults to an empty set.
11+ func values< Value: Sendable > (
12+ for keyPath: KeyPath < Self , Value > ,
13+ options: NSKeyValueObservingOptions = [ ]
14+ ) -> AsyncStream < Value > {
15+ let ( stream, continuation) = AsyncStream< Value> . makeStream( )
16+ let token : NSKeyValueObservation ? = self . observe ( keyPath, options: options) { object, _ in
17+ continuation. yield ( object [ keyPath: keyPath] )
18+ }
19+ // A nice side-effect of this is that the stream retains the token automatically.
20+ let locker = ValueLocker ( value: token)
21+ continuation. onTermination = { _ in
22+ locker. modify { $0 = nil }
23+ }
24+ return stream
25+ }
26+ }
27+
28+ @available ( iOS 18 , * )
529public extension NSObjectProtocol where Self: NSObject {
630 /// Observes changes to the specified key path on the object and asynchronously yields each value. Values must be `Sendable`.
731 ///
@@ -17,25 +41,22 @@ public extension NSObjectProtocol where Self: NSObject {
1741 values ( for: keyPath, options: options)
1842 . monitor ( changeHandler)
1943 }
44+ }
2045
21- /// Returns an `AsyncSequence` of `Value`s for all changes to the given key path on this object.
46+ @available ( iOS, introduced: 17 , obsoleted: 18 )
47+ public extension NSObjectProtocol where Self: NSObject {
48+ /// Observes changes to the specified key path on the object and asynchronously yields each value. Values must be `Sendable`.
2249 ///
2350 /// - Parameters:
2451 /// - keyPath: The key path to observe on this object. The value must be `Sendable`.
2552 /// - options: KVO options to use for observation. Defaults to an empty set.
26- func values< Value: Sendable > (
53+ /// - changeHandler: A closure that's executed with each new value.
54+ func monitorValues< Value: Sendable > (
2755 for keyPath: KeyPath < Self , Value > ,
28- options: NSKeyValueObservingOptions = [ ]
29- ) -> some AsyncSequence < Value , Never > {
30- let ( stream, continuation) = AsyncStream< Value> . makeStream( )
31- let token : NSKeyValueObservation ? = self . observe ( keyPath, options: options) { object, _ in
32- continuation. yield ( object [ keyPath: keyPath] )
33- }
34- // A nice side-effect of this is that the stream retains the token automatically.
35- let locker = ValueLocker ( value: token)
36- continuation. onTermination = { _ in
37- locker. modify { $0 = nil }
38- }
39- return stream
56+ options: NSKeyValueObservingOptions = [ ] ,
57+ changeHandler: @escaping @Sendable ( Value ) -> Void
58+ ) -> any AsyncCancellable {
59+ values ( for: keyPath, options: options)
60+ . monitor ( changeHandler)
4061 }
4162}
0 commit comments