##はじめに
WKWebViewを初めて使って調べたときに、
バラバラとした情報が多い印象で、
少々苦労した記憶があるので、備忘録として記載します。
とはいえ初心者向けです・・・!(`・ω・´)
##WKWebViewとは?
iOS 8では、これまで用いられていたブラウザエンジンであるUIWebViewに加え、「WKWebView」という新しいエンジンが追加されました。
WKWebViewはその実行速度、安定性、そして機能面でも、UIWebViewを大幅に向上しています。
要するに、WKWebViewを用いるだけで、アプリの実行速度が大幅にアップする。
引用元:ハイブリッドアプリの動作性能を飛躍的にアップさせるiOS 8の新ブラウザエンジンを検証する
要するに、アプリでWebページを表示している、あれです。(`・ω・´)
iOS8.0以上では、WKWebViewを使用するのが主流のようです。
(UIWebViewは非推奨。)
そして、WKWebViewは、storyboard上で設定できないらしい・・・!
(ソース:WKWebViewと向き合ってみた)ので、
今回は、WKWebViewをコードで画面に配置しました。
##環境
- X-code 9.4.1
- Swift4.1
##WKWebViewの基本的なデリゲートメソッド
WKNavigationDelegateに関してです。
記載しているメソッド以外にも色々ありますが、(どれを使うべきか、悩みました・・・)
今回は実際に使ったことのある基本的なメソッドを、4つ記載しています。
###①Webページの読み込み開始時に、処理を実行したい
/// リクエスト開始時に呼ばれる
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// ここに処理を書く!
decisionHandler(WKNavigationActionPolicy.allow) // WKNavigationActionPolicyを書かないとクラッシュします!
}
- Post時に呼ばれるイベント
- そのままページを表示するか、読み込みを中止する(ページを表示しない)かを決める
- リダイレクトが起これば連続して呼ばれる
- navigationTypeを見るとクリックよる遷移か、リダイレクトによる遷移かが分かる
-
decisionHandler(WKNavigationActionPolicy.allow)
→ページを表示する -
decisionHandler(WKNavigationActionPolicy.cancel)
→ページを表示しない
WKNavigationActionPolicyを書かないと、以下のようなエラーでクラッシュします。
地味に萎えるので、忘れないように注意しましょう!
Decides whether to allow or cancel a navigation.
Your delegate can either call the block immediately or save the block and call it asynchronously at a later time.
###②Webページが表示完了した時に、処理を実行したい
cookieの値チェックなどは、ここで行うと良さそうです。(`・ω・´)
(このメソッドか呼ばれる前は正しいcookieの値が取得できないことがありました。)
/// WebView表示完了
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// ここに処理を書く!
}
###③Webページ読み込みエラー時に、処理を実行したい
オフラインのチェック等をしたい場合に、これを使ってうまくいきました。(`・ω・´)
/// WebView読み込み時にエラーが発生
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
// ここに処理を書く!
}
###④Webページ読み込み失敗時に、処理を実行したい
/// WebView読み込み失敗
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
// ここに処理を書く!
}
+.:゚☆゚:.+.:゚☆゚:.+.:゚☆゚:.+ +.:゚☆゚:.+.:゚☆゚:.+.:゚☆゚:.+ +.:゚☆゚:.+.:゚☆゚:.+.:゚☆゚:.+
ちなみに、これらのメソッドは、親ViewControllerを拡張して
extension ViewController: WKNavigationDelegate {
}
内で呼びます。
それと、基本的なことですが、
import WebKit
を書かないと、上記のデリゲートメソッドを書いてもエラーになるので、忘れないようにしてください・・・w
参考:WebKit
##WKWebViewをAutoLayout設定してViewに配置する
画面いっぱいにWebViewを表示するだけなら
AutoLayoutはあまり意識しないでも済む(?!)かもしれませんが、
WebViewのサイズ調整、AutoLayoutが必要な場面は多々あるかなと思います。
(iPhoneXだとレイアウト調整必要ですし・・・)
今回は、フルスクリーン表示用と、
tabBarControllerに表示用に適当なメソッドを作りましたので、
その両方を、使い方と一緒に備忘録として記載しておきます。
※ちなみに、このtabBarControllerにwebViewを貼るだけをコードで書いてますw
ご了承ください。
/// WebView画面(フルスクリーンに表示時)のAutoLayoutを設定
///
/// - Parameters:
/// - webView: 表示するWebView
/// - view: WKWebViewを乗せるview
public func setLayoutFullScreenWebView(webView: WKWebView, view: UIView) {
// AutoLayout設定
webView.translatesAutoresizingMaskIntoConstraints = false
// webViewの幅をviewに合わせる
view.addConstraints([NSLayoutConstraint(item:webView, // AutoLayoutを設定する対象のview(ここではWKWebViewを指定)
attribute:NSLayoutAttribute.width, // AutoLayout設定対象のViewの起点を指定
relatedBy:NSLayoutRelation.equal, // 2つのview(ここでは親viewとWKWebView)の拘束関係を示すもの
toItem:view, // 拘束の基準となるview
attribute:NSLayoutAttribute.width, // 設定値はattributeと内容は同じ
multiplier:1.0, // 親viewに対して何パーセントの大きさにするかを設定(例:70%なら0.7)
constant:0)]) // 位置に加えるオフセット (例:親のビューの中心を基準にそろえるものの、それに対して常に30ポイントだけ正方向にずらしたい場合は30を設定する)
// webViewの高さをviewに合わせる
view.addConstraints([NSLayoutConstraint(item:webView,
attribute:NSLayoutAttribute.height,
relatedBy:NSLayoutRelation.equal,
toItem:view,
attribute:NSLayoutAttribute.height,
multiplier:1.0,
constant:0)])
}
/// WebView画面(tabbarControllerに表示時)のAutoLayoutを設定
///
/// - Parameters:
/// - webView: 表示するWebView
/// - view: WebViewを乗せるview
public func setLayoutWebView(webView: WKWebView, view: UIView) {
// AutoLayout設定
webView.translatesAutoresizingMaskIntoConstraints = false
// webViewの上端をviewに合わせる
view.addConstraints([NSLayoutConstraint(item:webView,
attribute:NSLayoutAttribute.top,
relatedBy:NSLayoutRelation.equal,
toItem:view,
attribute:NSLayoutAttribute.top,
multiplier:1.0,
constant:0)])
// webViewの幅をviewに合わせる
view.addConstraints([NSLayoutConstraint(item:webView,
attribute:NSLayoutAttribute.width,
relatedBy:NSLayoutRelation.equal,
toItem:view,
attribute:NSLayoutAttribute.width,
multiplier:1.0,
constant:0)])
// webViewの下端をviewに合わせる
view.addConstraints([NSLayoutConstraint(item:webView,
attribute:NSLayoutAttribute.bottom,
relatedBy:NSLayoutRelation.equal,
toItem:view,
attribute:NSLayoutAttribute.bottom,
multiplier:1.0,
constant: -49.0)]) // 画面下のtabbarを考慮
}
・translatesAutoresizingMaskIntoConstraints
コードでAutoLayoutを設定する時にはtranslatesAutoresizingMaskIntoConstraintsをオフにする必要があるみたい(デフォルトがONで思った通りのAutoLayoutが設定できない場合があるそう)なので、オフにします。
・NSLayoutConstraint
レイアウトはNSLayoutConstraintを使用しています。
(参考にした記事は、いちばん下の参考一覧に記載しています。)
##Webページを表示するリクエスト
実際にURLのWebページを表示するリクエストです!
これも、複数のViewControllerから呼び出せるように適当なメソッドを作っています。
/// リクエスト
///
/// - Parameters:
/// - urlString: 表示するURL
/// - webView: 表示先のwebView
public func requestUrl(urlString: String, webView: WKWebView) {
// URL設定
let encodedUrlString = urlString.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
// Webページを読み込む
let url = NSURL(string: encodedUrlString!)
let request = NSURLRequest(url: url! as URL)
webView.load(request as URLRequest)
}
おおまかな手順は下記です。(`・ω・´)
#####①URLエンコード
- [addingPercentEncoding(withAllowedCharacters:)]
(https://developer.apple.com/documentation/foundation/nsstring/1411946-addingpercentencoding)を使用して、URLで使えない文字を別の文字に置き換えます。
#####②URLをNSURLに変換
#####③NSURLRequestでリクエストを生成
#####④webViewにURLのWebページを表示するようにリクエスト
この辺に関しては、WKWebViewではありませんがswift:UIWebViewでwebページを引っ張ろう!!の記事がわかりやすかったです。
##実際にWebページを表示してみる
private var webView: WKWebView = WKWebView()
// 表示するURL
private let urlString: String = "https://www.yahoo.co.jp/"
override func viewDidLoad() {
super.viewDidLoad()
// WKWebViewの追加
webView = WKWebView(frame:CGRect(x: 0, y: 0, width: view.bounds.size.width, height: view.bounds.size.height))
view.addSubview(webView)
// 画面いっぱいに表示
self.setLayoutFullScreenWebView(webView: webView, view: view)
webView.navigationDelegate = self
self.requestUrl(urlString: urlString, webView: self.webView)
}
\(^o^)/
簡単にwebViewを表示することができましたw
##まとめ
勉強し始めの頃は、自分の好きなサイトをwebViewに表示するだけでも、
表示できたときに嬉しいですし、地味にテンション&モチベーションもあがるので
試しにWKWebViewを使ってみるのは、個人的に初心者の方におすすめできます\(^o^)/
##参考・WKWebView関連記事