[iOS 8] WKWebView で Web ページのロード中にステータスバーにインジケーターを表示してみる 〜 Objective-C 編

2014.09.18

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

前回

前回の記事 では、WKWebView でWeb ページを表示する部分を解説しました。今回は通信中によくステータスバーに表示するインジケーターの表示方法について解説します。

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

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

すると、以下のように Web ページの読み込み中に、ステータスバーにインジケーターが表示されていますね。

ios8-webkit-indicator-1

このように、サンプルプロジェクトでは、WKWebView で Web ページを読み込んでいる最中に、ステータスバーにインジケーターを表示するようにしています。

それでは早速ソースコードを見てみましょう。

ソースコードを見る

と言っても、インジケーターの表示に関する記述は以下の3箇所しかありません。

CLMWebBrowserViewController.m WKWebView クラスの loading プロパティの変更を監視(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;
    }
}

ご存知の方も多いと思いますが、そもそも、ステータスバーにインジケーターを表示するには、以下のように書きます。

// ステータスバーにインジケーターを表示する
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

// ステータスバーのインジケーターを非表示にする
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

サンプルプロジェクトで行なっていることを簡単に説明すると、「WKWebView クラスの loading プロパティの変更を監視して、ローディング中であればインジケーターを表示、そうでなければ非表示にする」ということをやっています。

WKWebView では loading が KVO に準拠した

サンプルプロジェクトだけ見ると、簡単なことしかやっていないように見えますが、実は非常に重要な点があります。 それは、WKWebView では loadingプロパティ が KVO に準拠したプロパティ になったことです。

実は、loading プロパティ自体は UIWebView にもあります。ただ、KVO に準拠していないため、上記のような実装ができませんでした。 なので、変わりに UIWebViewDelegate のメソッドを実装し、 Web ページのロード時・完了時に実行されるデリゲートメソッド内でインジケーターの表示・非表示を切り替えていました。

- (void)webViewDidStartLoad:(UIWebView*)webView
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
 
- (void)webViewDidFinishLoad:(UIWebView*)webView
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

すごい細かいですが、こんな気の利いた変更もあるんですね!

まとめ

WKWebView では loading プロパティの他にも、KVOに準拠したプロパティがいくつかあります。 次回は、その1つである estimatedProgress プロパティを使用して、プログレスを表示するところを解説します。