[iOS 8] WKWebView で Web ページのロード中にプログレスを表示してみる 〜 Objective-C 編

前回

前回の記事 では、WKWebView で Web ページのロード中にステータスバーにインジケーターを表示する部分を解説しました。今回はロード中のプログレス(進捗状況)を表示する方法について解説します。

サンプルプロジェクトを起動してみる

hirai-yuki/WebBrowserSample からサンプルプロジェクトをダウンロードして、Xcode 6 で開き、実行してみましょう(pod installを忘れずに!)。

すると、以下のように Web ページの読み込み中に、ナビゲーションバー下部にプログレスバーが表示されていますね。

ios8-webkit-estimatedprogress-1

SGNavigationProgress

サンプルプロジェクトでは、ナビゲーションバー下部にプログレスバー表示に SGNavigationProgress を利用しています。

sgryschuk/SGNavigationProgress

このOSSは、Safariのようにナビゲーションバー下部にプログレスバーを表示するための UINavigationBar のカテゴリーを定義しています。

UINavigationController+SGProgress.h をインポートして、- (void)setSGProgressPercentage:(float)percentage を実行するだけでナビゲーションバー下部にプログレスバーを表示してくれます。

表示に関しては本質ではないので、Web ページのロード中のプログレスがとれていることを確認するためにこれを利用します。

ソースコードを見る

サンプルプロジェクトで プログレス表示に関する記述は以下の3箇所です。

CLMWebBrowserViewController.m WKWebView クラスの estimatedProgress プロパティの変更を監視(KVO)
- (void)viewDidLoad
{
    [super viewDidLoad];

    // WKWebView インスタンスのプロパティの変更を監視する
    [self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
    [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil];
    [self.webView addObserver:self forKeyPath:@"loading" options:NSKeyValueObservingOptionNew context:nil];
    [self.webView addObserver:self forKeyPath:@"canGoBack" options:NSKeyValueObservingOptionNew context:nil];
    [self.webView addObserver:self forKeyPath:@"canGoForward" options:NSKeyValueObservingOptionNew context:nil];

    // 初回画面表示時にIntialURLで指定した Web ページを読み込む
    NSURL *url = [NSURL URLWithString:InitialURL];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self.webView loadRequest:request];
}

- (void)dealloc
{
    // WKWebView インスタンスのプロパティの変更を監視を解除する
    [self.webView removeObserver:self forKeyPath:@"estimatedProgress"];
    [self.webView removeObserver:self forKeyPath:@"title"];
    [self.webView removeObserver:self forKeyPath:@"loading"];
    [self.webView removeObserver:self forKeyPath:@"canGoBack"];
    [self.webView removeObserver:self forKeyPath:@"canGoForward"];
}
CLMWebBrowserViewController.m プログレスの表示を更新しているところ
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqualToString:@"estimatedProgress"]) {
        // estimatedProgressが変更されたら、プログレスバーを更新する
        [self.navigationController setSGProgressPercentage:self.webView.estimatedProgress * 100.0f];
    } else if ([keyPath isEqualToString:@"title"]) {
        // titleが変更されたら、ナビゲーションバーのタイトルを設定する
        self.title = self.webView.title;
    } else if ([keyPath isEqualToString:@"loading"]) {
        // loadingが変更されたら、ステータスバーのインジケーターの表示・非表示を切り替える
        [UIApplication sharedApplication].networkActivityIndicatorVisible = self.webView.loading;
        
        // リロードボタンと読み込み停止ボタンの有効・無効を切り替える
        self.reloadButton.enabled = !self.webView.loading;
        self.stopButton.enabled = self.webView.loading;
    } else if ([keyPath isEqualToString:@"canGoBack"]) {
        // canGoBackが変更されたら、「<」ボタンの有効・無効を切り替える
        self.backButton.enabled = self.webView.canGoBack;
    } else if ([keyPath isEqualToString:@"canGoForward"]) {
        // canGoForwardが変更されたら、「>」ボタンの有効・無効を切り替える
        self.forwardButton.enabled = self.webView.canGoForward;
    }
}

サンプルプロジェクトで行なっていることを簡単に説明すると、「WKWebView クラスの estimatedProgress プロパティの変更を監視して、estimatedProgressに変更があれば- (void)setSGProgressPercentage:(float)percentageを実行する」ということをやっています。

loading プロパティと同じですね。

estimatedProgress

iOS 8からは、WKWebView クラスの estimatedProgress プロパティより Web ページロード中のプログレスが取得できるようになりました。取得できる値は、0.0 〜 1.0 の double 型の値です。このプロパティは UIWebView にはなく、WKWebView 独自のプロパティです。

estimatedProgress プロパティは、loadingプロパティ同様、KVOに準拠しているので、サンプルプロジェクトのように実装できます。

まとめ

次回は estimatedProgress同様、WKWebViewで追加された titleURLプロパティについて解説します。