iOS 10以前はWKWebViewのリンクを3D TouchするとPeekでSafariViewが開き、PopでSafariへ移動するという動作でした。
これを移動することなく一つのアプリ内で完結したいということで、iOS 10では任意のview controllerを使うことが許されました。
サンプルでは全体httpsのサイトを使ってATS(App Transport Security)の設定を省けるようにしています。
以下サンプルコードです。
サンプル
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
let webView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
let web = self.webView
web.uiDelegate = self
web.allowsLinkPreview = true // Allow Peek & Pop 1/2
self.view.addSubview(web)
web.frame = self.view.bounds
// httpsではないhttpのページを表示したい時はXcodeでATSの設定をします
// ATSの設定方法は別途調べてください
// be careful with ATS (App Transport Security) if you want to open a non-https page
let url = URL(string: "https://www.amazon.co.jp/")!
let request = URLRequest(url: url)
web.load(request)
}
// Allow Peek & Pop 2/2
func webView(_ webView: WKWebView, shouldPreviewElement elementInfo: WKPreviewElementInfo) -> Bool {
return true
}
// Peek
func webView(_ webView: WKWebView, previewingViewControllerForElement elementInfo: WKPreviewElementInfo, defaultActions previewActions: [WKPreviewActionItem]) -> UIViewController? {
guard let url = elementInfo.linkURL else { return nil }
print("\(type(of: self)) \(#function) url:\(url)")
var actions = [WKPreviewActionItem]()
// Peekで表示しているページに対するアクションをview controllerへ渡します。
// 表示するアクションを選択することもできます。
// Just set all actions like
// actions = previewActions
// or filter any actions
for action in previewActions {
switch action.identifier {
case WKPreviewActionItemIdentifierOpen:
actions.append(action)
case WKPreviewActionItemIdentifierAddToReadingList:
actions.append(action)
case WKPreviewActionItemIdentifierCopy:
actions.append(action)
case WKPreviewActionItemIdentifierShare:
actions.append(action)
default: break
}
}
// アクションリストを表示したいのでUIViewControllerのサブクラスを使っています
let vc = WebPreviewViewController(url: url, actions: actions)
vc.preferredContentSize = vc.view.bounds.size
return vc
}
// Pop
func webView(_ webView: WKWebView, commitPreviewingViewController previewingViewController: UIViewController) {
if previewingViewController is WebPreviewViewController {
self.present(previewingViewController, animated: true) { }
}
}
}
class WebPreviewViewController: UIViewController {
var webViewPreviewActionItems: [WKPreviewActionItem] = []
var linkURL: URL?
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
convenience init(url: URL, actions: [WKPreviewActionItem]) {
self.init(nibName: nil, bundle: nil)
self.linkURL = url
self.webViewPreviewActionItems = actions
}
// 受け取ったアクションのリストを表示するため
override var previewActionItems: [UIPreviewActionItem] {
get {
return self.webViewPreviewActionItems
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Peek & Pop用のWKWebViewを表示
if let url = self.linkURL {
let web = WKWebView()
web.frame = self.view.bounds
self.view.addSubview(web)
web.load(URLRequest(url: url))
}
}
}
参照
iOS 10 Link Preview API in WKWebView
自作ブラウザアプリ(無料) にも近日実装予定