Developer News And Updates に2019年12月23日、UIWebViewは廃止され、今後、UIWebViewが使われているアプリは受付されないという記事が投稿されました。このブログでも次の記事に書きました。
今後はWKWebViewやSFSafariViewControllerを使用することが推奨されています。今回はUIWebViewからWKWebViewに置き換えるために、どのようなコードが書けるかをまとめました。
また、WKWebViewについてのその他の関連記事をこのブログに追加しています。この記事末の関連記事をご覧ください。
ページの読み込み
URLの読み込み
UIWebViewでURLを読み込む処理は次のようなコードです。
// Swift版
// UIWebView用
func load(url: URL) {
let request = URLRequest(url: url)
uiWebView.loadRequest(request)
}
// Objective-C版
// UIWebView用
- (void)loadWithURL:(NSURL *)url {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.uiWebView loadRequest:request];
}
WKWebViewもURLを読み込むコードは同じです。
// Swift版
// WKWebView用
func load(url: URL) {
let request = URLRequest(url: url)
wkWebView.load(request)
}
// Objective-C版
// WKWebView用
#import <WebKit/WebKit.h>
- (void)loadWithURL:(NSURL *)url {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.wkWebView loadRequest:request];
}
ローカルHTMLの表示
UIWebViewで文字列渡しでローカルHTMLを表示するコードは次のようになります。
// Swift版
uiWebView.loadHTMLString(html, baseURL: baseURL)
// Objective-C版
[self.uiWebView loadHTMLString:html
baseURL:baseURL];
WKWebViewの場合は次のようなコードです。WKWebViewの方は戻り値があるくらいの違いです。
// Swift版
_ = wkWebView.loadHTMLString(html, baseURL: baseURL)
// Objective-C版
[self.wkWebView loadHTMLString:html
baseURL:baseURL]
JavaScriptを実行する
UIWebViewでJavaScriptを実行するコードは次のようになります。
// Swift版
let result = uiWebView.stringByEvaluatingJavaScript(from: script)
// Objective-C版
id result = [self.uiWebView stringByEvaluatingJavaScriptFromString:script];
WKWebViewの場合は次のようなコードになります。
// Swift版
wkWebView.evaluateJavaScript(script) { (result, error) in
}
// Objective-C版
NSString *script = @"document.title";
[self.wkWebView evaluateJavaScript:script completionHandler:^(id _Nullable result, NSError * _Nullable error) {
}];
UIWebViewは同期処理になっていて、JavaScriptの実行が完了してからアプリに制御が戻ります。
WKWebViewの方は非同期処理になっていて、JavaScriptの実行が完了すると、指定したブロックが実行されます。
順番にJavaScriptを実行していくような処理は、完了ブロックで次のJavaScriptを実行していくように変更します。
ページの読み込み開始時と終了時に処理を行う
UIWebViewでは、UIWebViewDelegateプロトコルに適合させたクラスを実装して、処理を実装します。
// Swift版
import UIKit
class ViewController: UIViewController, UIWebViewDelegate {
@IBOutlet var uiWebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
uiWebView.delegate = self
load(url: URL(string: "http://www.example.com")!)
}
func load(url: URL) {
let request = URLRequest(url: url)
uiWebView.loadRequest(request)
}
/// ページの読み込み開始時に呼ばれる
func webViewDidStartLoad(_ webView: UIWebView) {
print("Start Loading Page")
}
/// ページの読み込み完了時に呼ばれる
func webViewDidFinishLoad(_ webView: UIWebView) {
print("Finish Loading Page")
}
/// 読み込みエラー発生時に呼ばれる
func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
print("Failed Loading Page: \(error)")
}
}
// Objective-C版
#import "ViewController.h"
@interface ViewController () <UIWebViewDelegate>
@end
@implementation ViewController
@synthesize uiWebView = _uiWebView;
- (void)viewDidLoad {
[super viewDidLoad];
self.uiWebView.delegate = self;
[self loadWithURL:[NSURL URLWithString:@"https://www.example.com"]];
}
- (void)loadWithURL:(NSURL *)url {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.uiWebView loadRequest:request];
}
/// ページの読み込み開始時に呼ばれる
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSLog(@"Start Loading Page");
}
/// ページの読み込み完了時に呼ばれる
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSLog(@"Finish Loading Page");
}
/// 読み込みエラー発生時に呼ばれる
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(@"Failed Loading Page: %@", error.localizedDescription);
}
@end
WKWebViewの場合は、WKNavigationDelegateプロトコルに適合させたクラスを実装して、処理を実装します。
WKNavigationDelegateプロトコルの方が少し細かい単位になっています。ページの読み込み処理を開始と内容受信が分かれています。例えば、接続出来ないURLが指定されたときに、 webView(_: didStartProvisionalNavigation:) メソッドは呼ばれますが、 webView(_: didCommit:) は呼ばれないという動作になります。
// Swift版
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
@IBOutlet var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
wkWebView.navigationDelegate = self
load(url: URL(string: "https://www.example.com/")!)
}
func load(url: URL) {
let request = URLRequest(url: url)
wkWebView.load(request)
}
/// ページの読み込み開始時に呼ばれる
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Start Provisional Navigation")
}
/// ページの内容受信開始時に呼ばれる
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
print("Did Commit")
}
/// ページの読み込み完了時に呼ばれる
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("Did Finish")
}
/// ページの読み込みエラー発生時に呼ばれる
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
print("Did Fail Provisional Navigation")
}
}
// Objective-C版
#import "ViewController.h"
@interface ViewController () <WKNavigationDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.wkWebView.navigationDelegate = self;
[self loadWithURL:[NSURL URLWithString:@"https://www.example.com"]];
}
- (void)loadWithURL:(NSURL *)url {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.wkWebView loadRequest:request];
}
/// ページの読み込み開始時に呼ばれる
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"Start Provisional Navigation");
}
/// ページの内容受信開始時に呼ばれる
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
NSLog(@"Did Commit");
}
/// ページの読み込み完了時に呼ばれる
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"Did Finish");
}
/// ページの読み込みエラー発生時に呼ばれる
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"Did Fail Provisional Navigation");
}
@end
まとめ
UIWebViewとWKWebViewを比較すると、WKWebViewの方が機能が多く、デリゲートメソッドも多いため、もっと細かく制御出来る印象です。UIWebViewが使えなくなっても困らないと思います。
関連性が高い記事
WKWebViewに関連するその他の記事です。