【2020/4/1更新】【Swift|ObjC 】 UIWebViewをWKWebViewで置き換える方法

2020年2月10日 Objective-Cのサンプルコードを追加しました。

2020年4月1日 関連記事へのリンクを追加しました。

Developer News And Updates に2019年12月23日、UIWebViewは廃止され、今後、UIWebViewが使われているアプリは受付されないという記事が投稿されました。このブログでも次の記事に書きました。

関連記事

2020年2月10日 WKWebViewとSFSafariViewControllerのどちらに置き換えるかについて書いた記事へのリンクを追加しました。 iOSアプリで埋め込みブラウザを使うには、次の3つの方法があ[…]

今後は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に関連するその他の記事です。

関連記事

このブログ用に作っているサンプルアプリで、WKWebViewを使っているものがあります。先日、Xcodeを11.4にアップデートしたところ、このアプリがクラッシュするようになってしまいました。 対応方法などを記事にまとめま[…]

関連記事

WKWebViewで認証されたページにアクセスしたいときは、確認証方法に合わせた処理が必要です。この記事ではHTTPのBasic認証に対応する方法を解説します。 全体的な流れ WKWebViewでBasic認[…]

 

スポンサーリンク
最新情報をチェックしよう!
>現役のプログラマーが書くプログラミング情報

現役のプログラマーが書くプログラミング情報

日々の開発の中での学びや分かったこと、調べたことなどを書いていくブログです。

CTR IMG