[Experiment] Dynamic domain embedding #1710
tgrapperon
started this conversation in
Ideas
Replies: 1 comment
-
This is really interesting. We currently have a large UIKit project with a lot of cross feature navigation and circular navigation. So far we have merged features when necessary. Something like this would be highly beneficial for us, especially as we migrate to SwiftUI and NavigationStack in the future. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hey!
While working on modularized projects, there are situations where some module
A
needs to embed a domain living in a moduleB
which itself need to present a domain from the moduleA
. The straightforward solution is to bring both features into the same module, but this is not scalable at all, and one may end with all features living in the same module.One solution to this kind of problem is brought by
NavigationStack
, but:So I wondered what would it take to embed fully erased domains, so we can for example dynamically embed
A
intoB
. I've managed to implement something that is relatively general, relatively usable and relatively testable. I've pushed results in a branch here.In this example, I'm injecting a full
Animations
domain into theTwoCounters
case study. In this case, they both live in the same module, but it would work the same if they'd live in different ones.DynamicDomains
are keyed by an arbitraryID
(andHashable
or aType
). In what follows, the integer42
is used a key for theAnimations
dynamic domain.In
TwoCounters
, we make some room for the dynamic domain's state:Similarly, we declare a case for this domain
We can then scope the dynamic domain in
body
:Now, in
TwoCounter
's view, we make room for the dynamic domain view:And that's it for
TwoCounters
. As you can see, we didn't refer to theAnimations
domain at all.Now, somewhere upstream in the view hierarchy (typically in a parent module that knows both
A
andB
), we bind a domain to42
using a view modifier:So we provide the reducer, an initial state and a view. All these values will be surfaced appropriately in
TwoCounters
Now, if we want to communicate between the two domains, we can for example define a general protocol that allows to conveniently extract or set values from the dynamic domain. In the sample from the branch, I'm using a simple protocol that allows to assign each coordinate of the circle's center from the animation domain to both
counter
counts fromTwoCounters
, and reciprocally.Finally, this dynamic embedding can be tested. We simply need to register the dynamic domain early with the
dynamicDomains
dependency:We can then perform tests more or less as usual. Equatability is inferred using existentials like it's done for
TaskResult
.I guess there are many ways to improve this, but it can probably already help in a few situations. Please let me know what you think!
Beta Was this translation helpful? Give feedback.
All reactions