(Swift|ObjC) How to replace UIWebView with WKWebView

On December 23 2019, the following article was post to the Developer News And Updates:

Updating Apps that Use Web Views

According to that, the App Store will no longer accept the app using UIWebView.

I also post the following article:

関連記事

To use the embedded web browser in an iOS App, you have three choices: UIWebView Class WKWebView class SFSa[…]

From now, WKWebView and SFSafariViewController are recommended. This article describes how to replace UIWebView with WKWebView.

スポンサーリンク

Load the web page

From URL

The code to load the web page from the specified URL with UIWebView is following:

// Swift
// With UIWebView
func load(url: URL) {
 let request = URLRequest(url: url)
 uiWebView.loadRequest(request)
}
// Objective-C
// With UIWebView
- (void)loadWithURL:(NSURL *)url {
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self.uiWebView loadRequest:request];
}

With WKWebView, the code is following. It is very similar.

// Swift
// With WKWebView
func load(url: URL) {
    let request = URLRequest(url: url)
    wkWebView.load(request)
}
// Objective-C
// With WKWebView
#import <WebKit/WebKit.h>

- (void)loadWithURL:(NSURL *)url {
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self.wkWebView loadRequest:request];
}

From Local HTML

The code to load the local HTML which is presented by the string with UIWebView is following:

// Swift
uiWebView.loadHTMLString(html, baseURL: baseURL)
// Objective-C
[self.uiWebView loadHTMLString:html
                       baseURL:baseURL];

With WKWebView is following. The difference between them is whether the result value is available or non-available (void).

// Swift
_ = wkWebView.loadHTMLString(html, baseURL: baseURL)
// Objective-C
[self.wkWebView loadHTMLString:html
                       baseURL:baseURL]

Execute JavaScript

The code to execute the JavaScript with UIWebView is following:

// Swift
let result = uiWebView.stringByEvaluatingJavaScript(from: script)
// Objective-C
id result = [self.uiWebView stringByEvaluatingJavaScriptFromString:script];

With WKWebView, the code is following:

// 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 execute the JavaScript synchronously, and returns the control to the app after completed.

WKWebView execute the JavaScript asynchronously, and the completion block will be performed after the script is completed.

If you want to execute the script step by step, you write the code to execute next script in the completion block.

Do something just after started or completed loading

You can do something just after started or completed loading the page with UIWebView, by implementing the class which is adopted to the UIWebViewDelegate protocol.

Next code is example:

// 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)
    }
    
    /// Called when start loading the page
    func webViewDidStartLoad(_ webView: UIWebView) {
        print("Start Loading Page")
    }
    
    /// Called after completed loading the page
    func webViewDidFinishLoad(_ webView: UIWebView) {
        print("Finish Loading Page")
    }
    
    /// Called when any errors are occurred
    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];
}

/// Called when start loading the page
- (void)webViewDidStartLoad:(UIWebView *)webView {
    NSLog(@"Start Loading Page");
}

/// Called after completed loading the page
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSLog(@"Finish Loading Page");
}

/// Called when any errors are occurred
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    NSLog(@"Failed Loading Page: %@", error.localizedDescription);
}

@end

With WKWebView, you can do more things by implementing the class which is adopted to the WKNavigationDelegate protocol.

For example, when the URL can’t be reached, webView(: didStartProvisionalNavigation:) method will be called but webView(:didCommit:) method will not.

// 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)
    }
    
    /// Called when start loading the page
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print("Start Provisional Navigation")
    }
    
    /// Called when start receiving the content
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        print("Did Commit")
    }
    
    /// Called after completed loading the page
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("Did Finish")
    }
    
    /// Called when any errors are occurred
    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];
}

/// Called when start loading the page
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"Start Provisional Navigation");
}

/// Called when start receiving the content
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    NSLog(@"Did Commit");
}

/// Called after completed loading the page
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    NSLog(@"Did Finish");
}

/// Called when any errors are occurred
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"Did Fail Provisional Navigation");
}

@end

Conclusion

Compare UIWebView and WKWebView, WKWebView has more function and delegate methods. I think it is more controllable class. I don’t think it is problem if the UIWebView goes away.

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

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

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

CTR IMG