Skip to content

Commit 8c2c207

Browse files
committed
Add didChange observation
1 parent 7a8f319 commit 8c2c207

6 files changed

+58
-8
lines changed

ViewEnvironmentUI/Sources/UIView+ViewEnvironmentPropagatingObject.swift

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ extension UIView: ViewEnvironmentPropagatingObject {
2929
@_spi(ViewEnvironmentWiring)
3030
public func setNeedsApplyEnvironment() {
3131
setNeedsLayout()
32+
33+
if let observing = self as? ViewEnvironmentObserving {
34+
observing.environmentDidChange()
35+
}
3236
}
3337
}
3438

ViewEnvironmentUI/Sources/UIViewController+ViewEnvironmentPropagatingObject.swift

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ extension UIViewController: ViewEnvironmentPropagatingObject {
3737
@_spi(ViewEnvironmentWiring)
3838
public func setNeedsApplyEnvironment() {
3939
viewIfLoaded?.setNeedsLayout()
40+
41+
if let observing = self as? ViewEnvironmentObserving {
42+
observing.environmentDidChange()
43+
}
4044
}
4145
}
4246

ViewEnvironmentUI/Sources/ViewEnvironmentObserving.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,20 @@ public protocol ViewEnvironmentObserving: ViewEnvironmentCustomizing {
5757
///
5858
func apply(environment: ViewEnvironment)
5959

60-
/// Consumers _must_ call this function when the envirnoment should be re-applied, e.g. in
60+
/// Consumers _must_ call this function when the environment should be re-applied, e.g. in
6161
/// `viewWillLayoutSubviews()` for `UIViewController`s and `layoutSubviews()` for `UIView`s.
6262
///
6363
/// This will call ``apply(environment:)`` on the receiver if the node has been flagged for needing update.
6464
///
6565
/// - Tag: ViewEnvironmentObserving.applyEnvironmentIfNeeded
6666
///
6767
func applyEnvironmentIfNeeded()
68+
69+
func environmentDidChange()
70+
}
71+
72+
extension ViewEnvironmentObserving {
73+
public func apply(environment: ViewEnvironment) {}
74+
75+
public func environmentDidChange() {}
6876
}

ViewEnvironmentUI/Sources/ViewEnvironmentPropagationNode.swift

+36-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import ViewEnvironment
2222
/// environment as it flows between two nodes.
2323
///
2424
@_spi(ViewEnvironmentWiring)
25-
public struct ViewEnvironmentPropagationNode: ViewEnvironmentCustomizing {
25+
public class ViewEnvironmentPropagationNode: ViewEnvironmentCustomizing, ViewEnvironmentObserving {
2626
public typealias EnvironmentAncestorProvider = () -> ViewEnvironmentPropagating?
2727

2828
public typealias EnvironmentDescendantsProvider = () -> [ViewEnvironmentPropagating]
@@ -39,14 +39,28 @@ public struct ViewEnvironmentPropagationNode: ViewEnvironmentCustomizing {
3939
didSet { setNeedsEnvironmentUpdate() }
4040
}
4141

42+
public var environmentDidChangeObserver: ((ViewEnvironment) -> Void)? {
43+
didSet { setNeedsEnvironmentUpdate() }
44+
}
45+
46+
public var applyEnvironment: (ViewEnvironment) -> Void {
47+
didSet { setNeedsEnvironmentUpdate() }
48+
}
49+
50+
private var needsEnvironmentUpdate: Bool = true
51+
4252
public init(
4353
environmentAncestor: @escaping EnvironmentAncestorProvider = { nil },
4454
environmentDescendants: @escaping EnvironmentDescendantsProvider = { [] },
45-
customizeEnvironment: @escaping (inout ViewEnvironment) -> Void = { _ in }
55+
customizeEnvironment: @escaping (inout ViewEnvironment) -> Void = { _ in },
56+
environmentDidChange: ((ViewEnvironment) -> Void)? = nil,
57+
applyEnvironment: @escaping (ViewEnvironment) -> Void = { _ in }
4658
) {
4759
self.environmentAncestorProvider = environmentAncestor
4860
self.environmentDescendantsProvider = environmentDescendants
4961
self.customizeEnvironment = customizeEnvironment
62+
self.environmentDidChangeObserver = environmentDidChange
63+
self.applyEnvironment = applyEnvironment
5064
}
5165

5266
public var environmentAncestor: ViewEnvironmentPropagating? { environmentAncestorProvider() }
@@ -58,6 +72,26 @@ public struct ViewEnvironmentPropagationNode: ViewEnvironmentCustomizing {
5872
}
5973

6074
public func setNeedsEnvironmentUpdate() {
75+
needsEnvironmentUpdate = true
76+
6177
setNeedsEnvironmentUpdateOnAppropriateDescendants()
6278
}
79+
80+
public func environmentDidChange() {
81+
guard let didChange = environmentDidChangeObserver else { return }
82+
83+
didChange(environment)
84+
}
85+
86+
public func applyEnvironmentIfNeeded() {
87+
guard needsEnvironmentUpdate else { return }
88+
89+
needsEnvironmentUpdate = false
90+
91+
apply(environment: environment)
92+
}
93+
94+
public func apply(environment: ViewEnvironment) {
95+
applyEnvironment(environment)
96+
}
6397
}

WorkflowUI/Sources/Hosting/WorkflowHostingController.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,13 @@ public final class WorkflowHostingController<ScreenType, Output>: UIViewControll
181181
}
182182

183183
extension WorkflowHostingController: ViewEnvironmentCustomizing, ViewEnvironmentObserving {
184-
public func apply(environment: ViewEnvironment) {
185-
update(screen: workflowHost.rendering.value, environment: environment)
186-
}
187-
188184
public func customize(environment: inout ViewEnvironment) {
189185
customizeEnvironment(&environment)
190186
}
187+
188+
public func environmentDidChange() {
189+
update(screen: workflowHost.rendering.value, environment: environment)
190+
}
191191
}
192192

193193
#endif

WorkflowUI/Sources/Screen/ScreenViewController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ open class ScreenViewController<ScreenType: Screen>: UIViewController {
7272
self.screen = screen
7373
let previousEnvironment = self.environment
7474
_environment = environment
75-
setNeedsEnvironmentUpdate()
7675
screenDidChange(from: previousScreen, previousEnvironment: previousEnvironment)
76+
setNeedsEnvironmentUpdate()
7777
}
7878

7979
open func screenDidChange(from previousScreen: ScreenType, previousEnvironment: ViewEnvironment) {}

0 commit comments

Comments
 (0)