はじめに
こんにちは、nukkyです。
今回はsuzukiさんの記事でWKWebViewが取り扱われたので、もう一つのWebViewで存在が忘れられがちなSFSafariViewControllerについてお話ししたいと思います。
suzukiさんの記事はこちらから
【Swift】WKWebViewでタップしたURLを取得する。
前提条件
Xcode 9.x
iOS 11 Simulator
Swift 4.0
SFSafariViewControllerとは
SFSafariViewControllerの特徴
iOS9.0以降使用可能でSafariの標準機能を備えたViewControllerを作成できます。
アプリのViewControllerでSafariを提供する形になるので、Safariアプリに飛ばした時よりアプリへの帰還率が高いです。
ただしカスタマイズ出来る部分が限られており、iOS11現在では、BarのTintColorやDoneボタンのスタイルなど一部しか変更がきかないです。
実装はとてもシンプルですがStoryboardから作成することは出来ません。
(これが忘れがちな理由かと。。。)
何と言っても一番の特徴はSafariブラウザとCookieやウェブサイトのデータの共有が可能です!
iOS11からのCookie同期について
SFSafariViewControllerの特徴としては、Cookie等Safariとの同期が出来ることによっていちいちログインする手間が省けることでした。
しかしiOS11から仕様が変わり、Cookie等のデータがSafariとは独立した領域に保存されるようになりました。
そこでSFAuthenticationSessionクラスという認証情報を共有するためのクラスが提供されました。これ使用することで、サードパーティーのSafari上での認証を共有することが可能になりました。
SFAuthenticationSessionについてはまた別の記事で詳しく紹介したいと思います。
SFSafariViewControllerとWKWebView
SFSafariViewControllerとWKWebViewの違い
SFSafariViewControllerとの違いとしてはローカルのHTMLファイルの読み込みが可能で、Xcode9以降Storyboard上からWKWebViewを利用可能、SFSafariViewControllerの基底クラスがUIViewControllerなのに対しWKWebViewは基底クラスがUIViewViewなので、Viewの一部をWKWebViewにするような扱いも可能。
それとカスタマイズの自由性はあるのですが、操作に必要なボタンがないので自前で閉じるボタンを追加したり、場合によっては戻るボタンを用意する必要があります。
どっちがいい?
見た目のカスタマイズ、フックやJavaScriptなどを使ってアプリのコンテンツとしてWebViewを使いたいならWKWebView。
Webページを表示するだけとかSafariアプリに投げるという使い方ならSFSafariViewControllerと結構住み分けはできていると思いますね。
どっちがいいかは結局アプリでどうWebViewを使いたいかで適した方を選択できると思います。
実装
まずは表示してみよう
SFSafariViewControllerを表示するだけであればとにかくシンプルです。
1 | import SafariServices |
1 2 3 4 5 | let url = URL(string:"https://www.google.co.jp/") if let url = url{ let vc = SFSafariViewController(url: url) present(vc, animated: true, completion: nil) } |
これで実行するとこのように表示されます。
SFSafariViewControllerDelegate
SFSafariViewControllerには以下のようなデリゲートが用意されています。
1 2 3 4 5 6 | //(1) optional public func safariViewController(_ controller: SFSafariViewController, didCompleteInitialLoad didLoadSuccessfully: Bool) //(2) optional public func safariViewController(_ controller: SFSafariViewController, excludedActivityTypesFor URL: URL, title: String?) -> [UIActivityType] //(3) optional public func safariViewControllerDidFinish(_ controller: SFSafariViewController) |
(1)は、最初に表示する画面の読み込み完了時に呼ばれます。
(2)は、アクションボタンタップ時に呼ばれます。
カスタムUIActivityを返却することもできます。
アクションボタンとは下の画像の右から二番目の四角から上矢印が出ているボタンです。
(3)は、左上の完了ボタンタップ時に呼ばれます。
ログを吐くだけですが実装は以下のになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | let vc = SFSafariViewController(url: url) vc.delegate = self extension ViewController: SFSafariViewControllerDelegate { func safariViewController(_ controller: SFSafariViewController, didCompleteInitialLoad didLoadSuccessfully: Bool) { print("didCompleteInitialLoad") } func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] { print("activityItemsForURL") return [UIActivity()] } func safariViewControllerDidFinish(_ controller: SFSafariViewController) { print("safariViewControllerDidFinish") } } |
さいごに
SFSafariViewControllerですが実装も簡単ですし特にWebViewにカスタム要素がないとか、Safariアプリに投げるとかするならこちらの方が使い勝手がいいと思います。
RE:ENGINESブログ「iOS記事」まとめページはこちらから