-
Notifications
You must be signed in to change notification settings - Fork 47
[feat]: Add support for automatic ViewEnvironment bridging in WorkflowUI #211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feat]: Add support for automatic ViewEnvironment bridging in WorkflowUI #211
Conversation
9ce7fc5
to
febb569
Compare
21936dc
to
8f096c2
Compare
@@ -42,11 +44,11 @@ open class ScreenViewController<ScreenType: Screen>: UIViewController { | |||
return ScreenType.self | |||
} | |||
|
|||
public private(set) final var environment: ViewEnvironment | |||
private var previousEnvironment: ViewEnvironment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to store this at all? I don't see it being used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's being used in update(screen:)
below.
8f096c2
to
0f8083a
Compare
…ndering's backing VCs
0f8083a
to
34595b1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly bikesheds 👍
super.viewWillLayoutSubviews() | ||
applyEnvironmentIfNeeded() | ||
} | ||
|
||
override public func viewDidLayoutSubviews() { | ||
super.viewDidLayoutSubviews() | ||
rootViewController.view.frame = view.bounds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated but we should move this to viewWillLayoutSubviews
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fairly confident we should but I was nervous to make this change as part of this work.
Let me know if you think it's worth doing now!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah, it's less risky to isolate that to a separate change. Just wanted to flag it.
@@ -42,11 +44,11 @@ open class ScreenViewController<ScreenType: Screen>: UIViewController { | |||
return ScreenType.self | |||
} | |||
|
|||
public private(set) final var environment: ViewEnvironment | |||
private var previousEnvironment: ViewEnvironment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bikeshed: lastEnvironment
or latestEnvironment
? It's not exactly "previous" until an update happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already built into the public API as previousEnvironment
in screenDidChange(from:,previousEnvironment:)
. I'd rather not change the public API and I think it's nice that this variable name matches the public API parameter it's it exists to support.
That being said, I don't feel super strongly! Let me know if you do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already built into the public API as
previousEnvironment
inscreenDidChange(from:,previousEnvironment:)
. I'd rather not change the public API and I think it's nice that this variable name matches the public API parameter it's it exists to support.
OK, so, my reasoning is that it's not the "previous" environment while it's being stored — it becomes the previous one during an update, when we read a new environment to replace it. Until then, it's just the latest one we observed. Not a big deal though.
WorkflowUI/Sources/ViewControllerDescription/ViewControllerDescription.swift
Outdated
Show resolved
Hide resolved
WorkflowUI/Sources/ViewControllerDescription/ViewControllerDescription.swift
Outdated
Show resolved
Hide resolved
// We must nil this out first or we'll hit an assertion which protects against overriding the ancestor when | ||
// some other system has already attempted to provide an override. | ||
viewController.environmentAncestorOverride = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, we could make PropagationNode
a class and update the same instance. I'm not sure if there's a performance concern to updating the override on every render due to the associated object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is an optimization I was talking through with @bencochran. You think it's worth doing now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think I'd lean towards just doing it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please re-review if/when you have time 🙏
WorkflowUI/Sources/ViewControllerDescription/ViewControllerDescription.swift
Outdated
Show resolved
Hide resolved
WorkflowUI/Sources/ViewControllerDescription/ViewControllerDescription.swift
Outdated
Show resolved
Hide resolved
import Workflow | ||
|
||
/// Drives view controllers from a root Workflow. | ||
public final class WorkflowHostingController<ScreenType, Output>: UIViewController where ScreenType: Screen { | ||
public typealias CustomizeEnvironment = (inout ViewEnvironment) -> Void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this alias be nested under the generic parent type? the fully-specified spelling will be parametrized by the screen/output, which might be unwieldy. then again, maybe nobody will need to reference it in that manner?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'd be surprised if we ever seen folks referencing the type directly in the context of WorkflowHostingController
usage.
I can move it out if we'd prefer though! There are a few opportunities in Market to re-use this type if it was at the top level. Let me know if you'd prefer we do move it out, and if so, what to name it/where to put it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
your call to relocate/rename if you think it makes sense – just a thought!
Overview
This PR adds deep integration of
ViewEnvironmentUI
toWorkflowUI
. This deep integration makes working with contexts that need to bridge between both systems much easier. For example, applications that have not fully adopted Workflow but utilize theViewEnvironment
for theme propagation viaViewEnvironmentUI
(as is true in Square's ios-register codebase).This PR is part of the larger effort to add support for automatic
ViewEnvironment
bridging betweenUIKit
propagation andWorkflowUI
propagation withinWorkflowUI
.See the associated proposal for more information.
Changes
This PR integrates
ViewEnvironmentUI
vanilla UIKitViewEnvironment
propagation support intoWorkflowUI
. This includes:ViewEnvironment
fromUIViewController
propagation intoScreen
'sViewEnvironment
withinWorkflowHostingController
.ViewEnvironment
fromScreen
'sViewEnvironment
intoUIViewController
propagation withinViewControllerDescription
.With these new features came some minor API adjustments:
ViewControllerDescription
now takes in aViewEnvironment
as a parameter. This environment is added into an ancestor propagation node above the described view controller so that it can be served to anyUIViewController
ViewEnvironment
queries (performed viaViewEnvironmentUI
's propagation system).WorkflowHostingController
now takes acustomizeEnvironment
closure instead of arootViewEnvironment
. This makes it possible to configure environment properties as theViewEnvironment
is bridged into theScreen
hierarchy without fully overwriting the entireViewEnvironment
.ScreenViewController
no longer takes anenvironment
in itsupdate(...)
function. TheEnvironment
is now managed by theViewControllerDescription
for theScreen
that it's backing. Theenvironment
parameter is still present in the initializer forScreenViewController
as it can be convenient to have valid environment state before the ancestor propagation node is configured above it (which is configured after initialization completes).Square Integration PRs
https://github.com/squareup/market/pull/6224
https://github.com/squareup/ios-register/pull/85648
Checklist