SFSafariViewControllerを導入してみました

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で表示されたページ
coordisnap.png

データ共有の例

実際にウェブサイトのデータが共有されるかを検証してみました(今回は Cookie を利用)。

『コーデスナップ』の SFSafariViewController で開いたページでデータを保存し、それを Safari で表示してみます(値: “コーデスナップで保存")。

コーデスナップで保存Safariで表示
coordisnap1.PNGcoordisnap2.PNG

今度はその逆を試してみます(値: “Safariで保存”)。

Safariで保存コーデスナップで表示
safari1.PNGsafari2.PNG

このように SFSafariViewController と Safari の間でデータが共有されていることが分かります。

利用上の注意点

リーダーモードについて

下記のイニシャライザを使えば、リーダーモードが利用可能な環境ではそれを有効にすることができます。

public init(URL: NSURL, entersReaderIfAvailable: Bool)

SFSafariViewController Class Reference

リーダーモードは便利な機能ですが、通常モードと比較すると表示内容に差異があります。

リーダーモード有効リーダーボタン押下で無効に
reader_on.pngreader_off.png

出典: ウィキペディア フリー百科事典

リーダーモードのときにリーダーボタンを押下すると通常モードに戻ります。ただし、リーダーモード自体が広く認知されているわけではなく、ユーザー体験が損なわれる原因にもなりかねません。そのため表示するページの用途を見極めた上での利用をおすすめします。『コーデスナップ』の場合は EC サイトを表示することが目的だったのでリーダーモードは無効にしています。

コンテンツブロッキングについて

インストールされたコンテンツブロッカーが有効になっている環境下では、SFSafariViewController で表示するページに対してもコンテンツブロッキングが働きます。こちらについてはリーダーモードのような有効・無効の制御はできないようです。

iOS 9未満では利用できない

SFSafariViewController は iOS 9 以上で利用できます。そのため iOS 9 未満をサポートするアプリでは、iOS バージョンによって処理の切り分けをする必要があります。

最後に

SFSafariViewController 利用のメリットは何といっても

  • Safari の洗練された UI を利用できる点
  • Safari とのデータ共有
  • 導入のかんたんさ

に尽きると思います。

今月開催される WWDC16 で次期バージョンの iOS が発表されれば、iOS 9 未満のバージョンをサポート対象から外すケースも増えてくると思います。そうなれば、SFSafariViewController も導入しやすくなるのではないでしょうか。


名無しのエンジニア
PointTown iOSアプリをObjective-CからSwift化した時のTips集
GMOテクノロジーブートキャンプでMySQLおじさんしてきた