Build a Hybrid SwiftUI app for iOS with Phoenix LiveView
I’ve succesfully published hybrid mobile apps with Turbolinks iOS in the past but Phoenix LiveViews are better suited due to the websocket event handling there is little (or no) HTTP navigation happening.
To demonstrate this we’re going to build an iOS app for Flappy Phoenix a LiveView game I created previously.
Create a new iOS project using Single View App
in Xcode
Make sure you’ve selected the SwiftUI
user interface
Using SwiftUI we need very little code to get the WebView onto the screen. Update the generated ContentView
with
// ContentView.swift
import SwiftUI
import WebKit
struct ContentView: View {
var body: some View {
WebView().edgesIgnoringSafeArea(.all)
}
}
struct WebView: UIViewRepresentable {
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.scrollView.isScrollEnabled = false
return webView
}
func updateUIView(_ webView: WKWebView, context: Context) {
let liveView = "https://flappy-phoenix.herokuapp.com/game"
if let url = URL(string: liveView) {
let request = URLRequest(url: url)
webView.load(request)
}
}
}
#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
This results in a playable iOS app that wraps the LiveView!
It is now possible to extend the interface with SwiftUI components to make it feel more native, while keeping the main body of the app served via the LiveView.
struct ContentView: View {
var body: some View{
NavigationView {
VStack{
WebView()
}
.navigationBarTitle(Text("Flappy Phoenix"))
.edgesIgnoringSafeArea(.all)
}
}
}
This is a simplified example, but hopefully it sparks your imagination of what is possible with LiveView hybrid apps.
In this case I haven’t had to make any modifications to the web application but often you might want to make some changes on the server-side eg. hiding the web navigation if you’re replacing it with native navigation.
To achieve this we can set a custom user agent in the WebView and then respond to that in the web application:
webView.customUserAgent = "FlappyPhoenix iOS"
If you have any tips or feedback please get in touch via Twitter.