Hotwire is designed from the ground up around the idea that you can start with a web app and add native functionality where it’s most needed.
Our broad strategy is to:
- preload the web view before users see it,
- detect when the web view is actually ready,
- then transition seamlessly from the loading screen to the web view.
We're going to refer to iOS and Swift throughout this article, but we found the same techniques just as applicable in our Android and Kotlin build.
Launch screens and loading scenes
iOS applications are required to provide a
launch screen implemented as a storyboard that is rendered by the OS while the application is launching. On Android, the developer has control over when the application transitions from launch screen to UI, but on iOS we can’t start loading Hotwire until we've attached a UI view.
We created a SwiftUI view that mimics the launch screen storyboard, and after a bit of time messing around learning constraints (did we mention we’re not iOS developers?) we had a seamless transition from launch screen to loading scene.
Preloading the webview
At this point, we hit a roadblock. Hotwire’s
VisitableViewController doesn’t start loading until it’s attached to a scene, and when it is attached it immediately injects its
WKWebView on top of the current scene.
After some trial and error, we realised that we can hide the attached
WKWebView by making the VisitableViewController's root view fully transparent. We built a SwiftUI Application that renders a stack of background, Hotwire VisitableViewController (as a
UIHostingController), and the loading screen we built in the previous step.
We put it all together with a view model that transitions the opacity of the web view once the content is ready. This lets us show the loading view while Hotwire does its thing.