Replies: 1 comment 1 reply
|
After learning about #286 I realized one could use |
1 reply
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.
When using the
observefunction, it is easy to inadvertently access observable values you did not intend to observe. This can cause the trailing closure ofobserveto run more often than expected. The issue becomes particularly noticeable when instantiating view controllers inside theobserveclosure:Accessing
child.viewforces the view to load immediately, which triggersloadViewandviewDidLoad. The same behavior occurs with standard container controllers such asUITabBarController. If you are interested in the details, you can take a look at this article by Boris Bugor.Because of this, if
viewDidLoadis used to start observing state, you may end up observing far more state than intended.The situation becomes even less predictable when dealing with
UIWindow’srootViewController. Callingwindow.makeKeyAndVisible()triggers not onlyviewDidLoad, but alsoviewIsAppearing,viewWillAppear, andviewDidAppear.Consider the following example:
With this setup, none of the lifecycle methods of
HomeViewControllerare safe places to start observing state. TheobserveinSceneDelegatewould end up tracking every observable accessed inside any of the lifecycle methods ofHomeViewController.Possible improvement
One possible solution takes inspiration from the
presentAPI:This API ensures that the presented controller only changes when the identity of
Itemchanges.A similar variant of
observecould be introduced:This approach makes the observed state explicit and prevents unexpected updates. I implemented a helper like this in my own codebase, and it has proven extremely helpful.
The previous example would then become:
With this design, inner view controllers can freely access observable properties without affecting the outer observation. The
onChangeclosure only runs when the identity ofrootchanges.Additional idea:
UIBindingReaderAnother improvement could be the introduction of a read-only version of
UIBinding(UIBindingReader, maybe?) that can be derived from aUIBinding. This reader would be used in situations where state should be observed but not mutated. Exactly the behavior needed byobserve(item:id:onChange:): what a coincidence!At the moment, if you want to prevent external mutation of a model's state while still allowing
UIBindings to be created, you typically have to rely on not-so-ergonomic code like this:A more natural approach might look like this:
I know that a simple key path could serve this situation, but the
UIBindingReaderapproach feels more direct. This becomes especially true whenItemdoes not conform toIdentifiable:vs.
SwiftUI already has this concept, and since UIKitNavigation aims to modernize UIKit in light of SwiftUI, it seems reasonable for it to adopt something similar.
Conclusion
Looking forward to hearing your feedback on these ideas!
All reactions