9
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[SwiftUI] SFSafariViewControllerを使用したInAppブラウザ表示

Posted at

今回はSFSafariViewControllerを使用したInAppブラウザ表示の実装例を書いていこうと思います。

View側(NavigationLinkと組み合わせて使用しない方が良さそう)

ここでわざわざタイトルに書いているのは、NavigationLinkとSFSafariViewControllerの相性が悪かった為です。最初の実装ではNavigationLinkのdestinationにSafariViewを設定して表示させようとしたのですが、そうするとヘッダーの完了ボタンが効かなくなりブラウザを閉じることができなくなるなどいくつかの不具合に遭遇しました。なのでfullScreenCoverを使用して実装する方針へ切り替えることにしました。参考コードは下記のようになります。

@State var isSafariWebViewShow: Bool = false
Button {
  isSafariWebViewShow = true
} label: {
  Text("詳しく見る")
}
.fullScreenCover(isPresented: $isSafariWebViewShow, content: {
  SafariWebView(url: URL(string: "\(url)")!, onClose: {
    // 非表示後に何かやりたい処理があればここに書く
  })
})

SafariWebViewの詳細実装

import SafariServices
import SwiftUI

struct SafariWebView: UIViewControllerRepresentable {
  var url: URL
  var onClose: () -> Void

  func makeUIViewController(context: Context) -> SFSafariViewController {
    let safariViewController = SFSafariViewController(url: url)
    safariViewController.delegate = context.coordinator
    return safariViewController
  }

  func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {}

  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }

  class Coordinator: NSObject, SFSafariViewControllerDelegate {
    var parent: SafariWebView

    init(_ safariWebView: SafariWebView) {
      self.parent = safariWebView
    }

    func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
      parent.onClose()
    }
  }
}

実装のポイント

SFSafariViewControllerはUIViewControllerを継承しているクラスなので、SwiftUIで使用する際にはUIViewControllerRepresentableを使用する必要があります。書き方についてはどこにでもあるテンプレートパターンと同じです。今回の場合はSafariWebViewが閉じた後に特定のイベントを発火させる必要がありました。SFSafariViewControllerのDelegateには終了を検知するイベントが用意されているので、それを使用する為にCoordinatorクラスを定義しています。特に不要であればこのあたりも省略して書くことができます。

終わりに

以上がSFSafariViewControllerを使用したInAppブラウザでの表示方法となります。UIViewControllerRepresentableの扱いに慣れていれば、そこまでSafariWebView側の実装は難しくなく、むしろView側での表示方法がSwiftUI側のViewコンポーネントとの相性の兼ね合いもあり時間が掛かった印象です。

9
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?