SFSafariViewController
はナビゲーション時の振る舞いや状態管理を自身で有しているので、予めUIViewControllerRepresentable化してSwiftUIで制御しようとするとコーディングが複雑になる。なのでそれを簡単に行えるパターンを考えてみた。
import SwiftUI
import SafariServices
public struct RepresentControllerView: UIViewControllerRepresentable {
private var uiViewController: UIViewController
public init(uiViewController: UIViewController) {
self.uiViewController = uiViewController
}
public func makeUIViewController(context: Context) -> UIViewController {
uiViewController
}
public func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}
public final class HostingController<Content: View>: UIHostingController<Content>, ObservableObject {}
public struct HostingControllerView<Content: View>: View {
private var c: HostingController<Content>
public init(rootView: Content) {
self.c = HostingController(rootView: rootView)
}
public var body: some View {
RepresentControllerView(uiViewController: c).environmentObject(c)
}
}
struct ContentView: View {
struct RootView: View {
@EnvironmentObject var viewController: HostingController<RootView>
private let urlString = "https://example.org"
func present() {
let safari = SFSafariViewController(url: URL(string: urlString)!)
viewController.present(safari, animated: true, completion: nil)
}
var body: some View {
Button(urlString, action: present)
}
}
var body: some View {
HostingControllerView(rootView: RootView())
}
}
期待通りウェブをフルスクリーンモーダルで表示が出来た。