はじめに
Amazonアプリとか食べログアプリとかTwitterアプリとかをiOSデバイスに入れてると、iOSアプリ内のWebViewとかでUniversal Linksに引っかかって、
アプリ内で表示したいのに!! って言うことがあって、調べたらなんか面白いのを見つけてやってみたら上手く行ったのでそれ
環境
- Xcode9.2
- iPhone実機
現状の動作
食べログアプリで検証していきます。
1度食べログアプリは開いたことがある前提で。
UIWebViewでGoogle検索(他のエンジンでも)すると動画のように食べログアプリに遷移します。SFSafariViewControllerでも再現できました。
また、SFSafariViewControllerは以下で普通に動作させています。
import UIKit import SafariServices class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let url = URL(string: "https://google.com")! let safari = SFSafariViewController(url: url) present(safari, animated: true, completion: nil) } }
対策
参考にした記事が以下です。
WKWebViewを使って実装します。
Xcode9 かつ DevelopmentTargetがiOS11以上の場合はInterfaceBuilderで実装できますが、今回はiOS10もサポートしているということにしてソースコードでWKWebViewを作っていきます。
import UIKit import WebKit class ViewController: UIViewController { private var wkWebView: WKWebView! override func viewDidLoad() { super.viewDidLoad() wkWebView = WKWebView(frame: .zero) let url = URL(string: "https://google.com")! wkWebView.load(URLRequest(url: url)) wkWebView.navigationDelegate = self view.addSubview(wkWebView) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } override func viewDidLayoutSubviews() { if #available(iOS 11.0, *) { wkWebView.frame = CGRect(x: 0, y: 0, width: view.bounds.size.width, height: view.bounds.size.height - view.safeAreaInsets.bottom) } else { wkWebView.frame = CGRect(x: 0, y: 0, width: view.bounds.size.width, height: view.bounds.size.height) } super.viewDidLayoutSubviews() } } // MARK: - WKNavigationDelegate extension ViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) { UIApplication.shared.isNetworkActivityIndicatorVisible = true decisionHandler(WKNavigationActionPolicy(rawValue: WKNavigationActionPolicy.allow.rawValue + 2)!) } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { UIApplication.shared.isNetworkActivityIndicatorVisible = false } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { UIApplication.shared.isNetworkActivityIndicatorVisible = false } }
いきなりですが、全体的な簡単なコードを置いておきます。
iOS11をサポートするということは必然的にiPhoneXをサポートすることになるので、SafeAreaについての振り分けを viewDidLayoutSubviews()
でしています。
一応、動作動画です。
なんで WKNavigationActionPolicy.allow.rawValue + 2 なの?
Apple Developer Documentation Apple Developer Documentation
上記、ドキュメントにも書かれている通り WKNavigationActionPolicy は、 cancel
と allow
しかない状態です。
誰かがどこぞから見つけてきた抜け穴のようですね。調べても一切情報がでてきません。出てきたとしても出処によってはNDA的な意味で紹介できませんが。
ちなみに + 1
と + 3
をしてみたのですがやはり動きません。なんなんでしょうね、全然わからん
最後に
はい。なんか微妙な締めくくりですが、 WKWebView ですごく不思議な裏技を使ってUniversal Linksを回避するという内容でした。
多分今年の技術記事はこれが最後かなと。
明日明後日多分、今年の振り返り記事を書くかな?