ステータステキストを Cocoa バインディングを使って表示する


HOME > TIPS > はじめてのブラウザのつくりかた > はじめてのブラウザのつくり方 10.3 > ステータステキストを Cocoa バインディングを使って表示する

ステータステキストを Cocoa バインディングを使って表示する

今回は、ステータステキストの表示だ。それぞれのウィンドウの下側にある、ステータスバーに、現在の読み込み状況や、マウスが指し示しているリンクを表示する、ステータステキストを表示しよう。こういうのは、Cocoa バインディングの得意技だ。

完成予想図は、こんな感じ。

statusText.jpg
図3-1 ステータステキスト

3.1 ステータステキストのための MVC

Cocoa バインディングを使うには、まず始めに、ビュー、コントローラ、モデルをどう設定するのか決めなくてはいけない。これが、Cocoa バインディングの第一歩だ。

この例では、ビューは、ウィンドウ上のテキストフィールドになる。コントローラは、1 つのテキストしか表示しないので、NSObjectController を使おう。モデルとなるクラスは、ステータステキストを表すプロパティを持つ。このテキストは、WebView の現在の状態を示すものなので、WebView のデリゲートにするのが最も簡単だね。ということで、WebViewDelegate というクラスを作り、これをモデルにする。

ということで、ビュー、コントローラ、モデルの関係は、次の図のようになるんだ。

mvc.jpg
図3-2 MVC 構造

実装しなくてはいけないのは、WebViewDelegate クラスだけだ。

3.2 表示するステータス

実装を始める前に、どういうステータスを表示するのか、明らかにしておこう。それと、そのステータスのためには、どのデリゲートメソッドが使えるのかも、考察しておく。

■ページの読み込み状況

ページの読み込みを開始したら、「Loading "URL 名"」というテキストを表示する。そして、読み込みが完了したら、消すことにする。これには、WebFrameLoadDelegate のメソッドを使う。読み込み開始は webView:didStartProvisionalLoadForFrame: を、完了は webView:didFinishLoadForFrame: を使って、通知を受け取ることにしよう。

あと、読み込み時のエラーも表示する。これには、同じく WebFrameLoadDelegate のメソッドである、webView:didFailProvisionalLoadWithError:forFrame: と、webView:didFailLoadWithError:forFrame: を使う。

■マウスが指し示しているリンク先

Web ページの上でマウスを動かして、リンクの上に来たときは、そのリンクを表示することにしよう。これは、WebUIDelegate の webView:mouseDidMoveOverElement:modifierFlags: で取得できる。

■Java Script によるステータステキスト

Java Script を使うと、ステータステキストを表示することができる。これも、表示しよう。WebUIDelegate の webView:setStatusText: を実装することで対応できる。

3.3 実装

ということで、実装だ。前のプロジェクトの続きからやるよ。

1. 今回は、MyDocument.nib を編集する。MyDocument.nib を開いて、Interface Builder に映ってくれ。

2. WebView のデリゲートとなるクラスを作る。NSObject のサブクラスを作って、WebViewDelegate という名前をつけよう。アウトレットとして、念のために、webView を持たせておく。インスタンス化もしておく。ファイルも作って、プロジェクトに登録しておく。

3. WebViewDelegate と WebView を接続する。まず、WebView のデリゲートとして、WebViewDelegate を設定する。ついでだから、全部の種類のデリゲートをつなげてしまおう。次の図のような感じ。

outlets-5.jpg
図3-3 アウトレットの接続

あと、WebViewDelegate のアウトレットを、WebView とつないでおく。

4. コントローラを作る。今回は、NSObjectController を使う。パレットからドラッグして、インスタンスを作ってくれ。名前は、BrowserController とでもしておこう。アウトレットの content には、WebViewDelegate を接続する。つまり、WebViewDelegate がモデルになるんだね。

5. ステータスを表示するためのテキストフィールドを追加する。ブラウザウィンドウの下の方に、次の図のように、テキストフィールドを追加しよう。

textField.jpg
図3-4 テキストフィールド

6. ステータスのためのテキストフィールドに、バインディングを設定する。テキストフィールドを選択して、Info パネルの Bindings パネルを開いてくれ。そっから、value のバインディングの設定をする。次のようにする。

・Bind to には、BrowserController を設定する。

・Controller Key には、selection を設定する。

・Model Key Path には、statusText を設定する。


bindings-1.jpg
図3-5 テキストフィールドのバインディング

statusText ってのが、ステータスとして表示する文字列のプロパティだ。WebViewDelegate が持つことになる。

ここまでできたら、Xcode に戻ろう。

7. WebViewDelegate のインタフェースを変更する。WebViewDelegate.h を開いてくれ。ここに、ステータスの文字列を管理するための、statusText っていうプロパティを追加する。具体的には、NSString 型のインスタンス変数を追加する。次のようにしてくれ。名前は大事だ。

WebViewDelegate.h

@interface WebViewDelegate : NSObject
{
  NSString* statusText;

  IBOutlet id webView;
}
@end

8. WebViewDelegate.m を編集する。WebView のデリゲートのうち、ステータス表示に関係するものを実装するんだ。さっき説明したように、今回は、webView:didStartProvisionalLoadForFrame:、 webView:didFinishLoadForFrame:、 webView:didFailProvisionalLoadWithError:forFrame:、 webView:didFailLoadWithError:forFrame:、 webView:mouseDidMoveOverElement:modifierFlags:、 webView:setStatusText: を実装する。これらのメソッドの中では、適当なステータステキストを作って、statusText プロパティとして設定するんだ。設定するときには、setValue:forKey: を使うのをお忘れなく。

例として、webView:didStartProvisionalLoadForFrame: の実装を紹介しよう。


WebViewDelegate.m

- (void)webView:(WebView*)sender
didCommitLoadForFrame:(WebFrame*)frame
{
  if ([sender mainFrame] == frame) {
    NSString* link;
    link = [[[[frame dataSource] request] URL] absoluteString];

    // 読み込み状況をステータスバーに表示します
    [self setValue:[NSString stringWithFormat:@"Loading \"%@\"", link]
        forKey:@"statusText"];
  }
}

NSURLRequest から、読み込んでいる URL を取り出して、文字列を作っているんだ。それを、setValue:forKey: を使って、statusText プロパティに設定しているだけだ。これを行うと、テキストフィールドが自動的に更新される。

他のメソッドについては、ソースコードを参照してくれ。

9. ビルドして実行する。いろいろ Web ページをブラウザしてみて、ステータステキストの動作を確認してみてくれ。

browser-10.jpg
図3-6 MyFirstBrowserPanther3 動作図


■ここまでのプロジェクト:
MyFirstBrowserPanther3.zip