前置き
SwiftUIとSFSafariViewControllerを併せて使おうとしたところ、困ったことになったので記録。
やりたかったこと
- 適当なボタンをタップ
- 対応するWebページを表示するViewへ遷移 ← ここでSFSafariViewControllerを使用
環境
- Xcode: 11.0
- Swift: 5.1
- 実機: 13.1.1
SFSafariViewControllerは以下のように使っています。
SafariView.swift
struct SafariView: UIViewControllerRepresentable {
typealias UIViewControllerType = SFSafariViewController
var url: URL
func makeUIViewController(context: UIViewControllerRepresentableContext<SafariView>) -> SFSafariViewController {
return SFSafariViewController(url: url)
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: UIViewControllerRepresentableContext<SafariView>) {
}
}
NavigationLinkで簡単に遷移出来るらしいからやってみよう
下のようにViewを作ると、
struct PushTestView: View {
var body: some View {
NavigationView {
NavigationLink(destination: WebView()) {
Text("Show web page")
}
}
}
}
struct WebView: View {
var body: some View {
SafariView(url: URL(string: "https://apple.com")!)
}
}
このようになります。
遷移元 | 遷移先 |
---|---|
元のNavigationBarが残り、画面下にもスペースが残ります。
画面下のスペースは
SafariView(url: URL(string: "https://apple.com")!)
.edgesIgnoringSafeArea(.bottom)
で対処出来ますが(下図)、NavigationBarが残るのはどうにもならない気がします。
モーダルにしよう
NavigationLinkを使った遷移がうまくいかなかったため、モーダルにすることを試してみます。
.sheet
修飾子を使う
以下のようにViewを作り、同じようにSFSafariViewControllerへ遷移させてみました。
struct ModalTestView: View {
@State var showModal = false
var body: some View {
NavigationView {
Button(action: {
self.showModal.toggle()
}) {
Text("Show Web page")
}
.sheet(isPresented: $showModal) {
WebView()
}
}
}
}
struct WebView: View {
var body: some View {
SafariView(url: URL(string: "https://apple.com")!)
.edgesIgnoringSafeArea(.all)
}
}
ここでも問題があり、普通なら出来るはずの上から下へのスワイプでモーダルを閉じることが出来ません。
その代わりに左から右へのエッジスワイプで完了を押した時と同じ挙動でモーダルが閉じてしまいます。
(上のgifでは1回目は完了を押して、2回目はエッジスワイプで閉じています。)
動きが分かりやすいようにシミュレーターを使うと、下のgifのようになります。
実機と同じ挙動です。
おわりに
いつか修正されるのを待ちます。