11import Combine
22
3- // Inspired by https://stackoverflow.com/a/67133582/670119
4-
53extension Publisher {
64
75 /// Transforms elements from the upstream publisher into a tuple containing the current and
@@ -19,9 +17,19 @@ extension Publisher {
1917 ///
2018 /// - Returns: A publisher that emits a tuple of the previous and current elements from the
2119 /// upstream publisher.
20+ ///
21+ /// - Note: Until version 0.3.0 of the library, this was implemented using `.scan` (see
22+ /// [this post](https://stackoverflow.com/a/67133582/670119)). However, that approach
23+ /// strongly retained previous values and could keep them in memory longer than expected
24+ /// when `Output` was a reference type. This version avoids that by using a local variable
25+ /// inside `map`, which does not retain previous values beyond each emission.
2226 public func withPrevious( ) -> AnyPublisher < ( previous: Output ? , current: Output ) , Failure > {
23- self . scan ( Optional< ( Output? , Output) > . none) { ( $0? . 1 , $1) }
24- . compactMap { $0 }
27+ var previous : Output ?
28+ return self
29+ . map { current in
30+ defer { previous = current }
31+ return ( previous: previous, current: current)
32+ }
2533 . eraseToAnyPublisher ( )
2634 }
2735
@@ -42,10 +50,21 @@ extension Publisher {
4250 /// emission.
4351 /// - Returns: A publisher that emits a tuple of the previous and current elements from the
4452 /// upstream publisher.
53+ ///
54+ /// - Note: Until version 0.3.0 of the library, this was implemented using `.scan` (see
55+ /// [this post](https://stackoverflow.com/a/67133582/670119)). However, that approach
56+ /// strongly retained previous values and could keep them in memory longer than expected
57+ /// when `Output` was a reference type. This version avoids that by using a local variable
58+ /// inside `map`, which does not retain previous values beyond each emission.
4559 public func withPrevious(
4660 initialValue: Output
4761 ) -> AnyPublisher < ( previous: Output , current: Output ) , Failure > {
48- self . scan ( ( initialValue, initialValue) ) { ( $0. 1 , $1) }
62+ var previous = initialValue
63+ return self
64+ . map { current in
65+ defer { previous = current }
66+ return ( previous: previous, current: current)
67+ }
4968 . eraseToAnyPublisher ( )
5069 }
5170
0 commit comments