SFSafariViewControllerを導入してみました

はじめに
こんにちは若林です。
iOS 9 ではウェブページを表示するために SFSafariViewController
を利用できます。
弊社でもファッションコーディネート共有アプリ『CoordiSnap(コーデスナップ)』のリニューアルにともない、SFSafariViewController
を導入してみました。
SFSafariViewController とは
SFSafariViewController
はウェブブラウジングの標準 UI を提供する View Controller で、次のような特徴があります。
- Safari の機能(リーダー, オートフィル, 不正サイト検知, コンテンツブロッキングなど)が使える
- Cookie などウェブサイトのデータを Safari と共有できる
- ウェブページ内インタラクション, オートフィルデータ, ブラウジング履歴, ウェブサイトのデータなどにアプリからアクセスすることはできない
- アプリ・Safari 間の(セキュアな)データ連携についてプログラマが考える必要がない
また、次のような UI で構成されています。
- 読取専用のアドレスフィールドとセキュリティインジケーター、リーダーボタン
- 「完了」ボタン
- ナビゲーションボタン
- アクティビティを立ち上げるアクションボタン
- ページを Safari で開くためのボタン
SFSafariViewController Class Reference
なぜ導入したか
『コーデスナップ』ではコーディネートの着用アイテムを EC サイトからその場で購入することができます。
ユーザーの行動履歴を見ていくと、『コーデスナップ』アプリで閲覧された商品が、何日か後に購入されているケースがちらほらありました。これにはアプリ内 WebView 以外の経路(ウェブブラウザなど)からの購入も含まれます。そのような場合でも、アプリと Safari 間でデータが共有されていればコンバージョンをより把握しやすくなるのでは、と思ったのが導入の理由です。
導入方法
SFSafariViewController のインターフェイス
SFSafariViewController
のインターフェイスはとてもシンプルです。
weak public var delegate: SFSafariViewControllerDelegate?
public init(URL: NSURL, entersReaderIfAvailable: Bool)
public convenience init(URL: NSURL)
optional public func safariViewController(controller: SFSafariViewController, activityItemsForURL URL: NSURL, title: String?) -> [UIActivity]
optional public func safariViewControllerDidFinish(controller: SFSafariViewController)
optional public func safariViewController(controller: SFSafariViewController, didCompleteInitialLoad didLoadSuccessfully: Bool)
提供されているデリゲートメソッドは上記の三つで、それぞれ
- アクションボタン押下によるアクティビティアイテムの選択
- 「完了」ボタン押下による
SFSafariViewController
の終了 - 初期ローディングの完了
が通知されます。
ウェブページを表示する
導入は至ってかんたんです。SafariServices.framework
をプロジェクトにインポートして、ほんの数行のコードを書くだけで、洗練されたウェブブラウジングの UI が利用できます。
import SafariServices
final class SampleViewController : SFSafariViewControllerDelegate {
@IBAction func presentSafariViewController(sender: AnyObject) {
let safariViewController = SFSafariViewController(URL: NSURL(string: "https://coordisnap.com")!)
presentViewController(safariViewController, animated: true, completion: nil);
}
}
SFSafariViewControllerで表示されたページ |
---|
![]() |
データ共有の例
実際にウェブサイトのデータが共有されるかを検証してみました(今回は Cookie を利用)。
『コーデスナップ』の SFSafariViewController
で開いたページでデータを保存し、それを Safari で表示してみます(値: “コーデスナップで保存")。
コーデスナップで保存 | Safariで表示 |
---|---|
![]() | ![]() |
今度はその逆を試してみます(値: “Safariで保存”)。
Safariで保存 | コーデスナップで表示 |
---|---|
![]() | ![]() |
このように SFSafariViewController
と Safari の間でデータが共有されていることが分かります。
利用上の注意点
リーダーモードについて
下記のイニシャライザを使えば、リーダーモードが利用可能な環境ではそれを有効にすることができます。
public init(URL: NSURL, entersReaderIfAvailable: Bool)
SFSafariViewController Class Reference
リーダーモードは便利な機能ですが、通常モードと比較すると表示内容に差異があります。
リーダーモード有効 | リーダーボタン押下で無効に |
---|---|
![]() | ![]() |
出典: ウィキペディア フリー百科事典
リーダーモードのときにリーダーボタンを押下すると通常モードに戻ります。ただし、リーダーモード自体が広く認知されているわけではなく、ユーザー体験が損なわれる原因にもなりかねません。そのため表示するページの用途を見極めた上での利用をおすすめします。『コーデスナップ』の場合は EC サイトを表示することが目的だったのでリーダーモードは無効にしています。
コンテンツブロッキングについて
インストールされたコンテンツブロッカーが有効になっている環境下では、SFSafariViewController
で表示するページに対してもコンテンツブロッキングが働きます。こちらについてはリーダーモードのような有効・無効の制御はできないようです。
iOS 9未満では利用できない
SFSafariViewController
は iOS 9 以上で利用できます。そのため iOS 9 未満をサポートするアプリでは、iOS バージョンによって処理の切り分けをする必要があります。
最後に
SFSafariViewController
利用のメリットは何といっても
- Safari の洗練された UI を利用できる点
- Safari とのデータ共有
- 導入のかんたんさ
に尽きると思います。
今月開催される WWDC16 で次期バージョンの iOS が発表されれば、iOS 9 未満のバージョンをサポート対象から外すケースも増えてくると思います。そうなれば、SFSafariViewController
も導入しやすくなるのではないでしょうか。