Cocoaはやっぱり!
インターネットにアクセスしよう
Web Kit : DRAFT

このドキュメント

このドキュメントは、Web Kitについてのドラフト的なものについて書き留めたものです。調査中のものも含まれますので、ご注意ください。

文字列で与えられた計算式を計算する方法

文字列で " (1+2)/4 " なんていう文字列を与えられた時にこれを計算する場合、自前でやるとちょっと面倒ですが、Cocoa + Web Kit なら簡単に計算できます。

WebViewには stringByEvaluatingJavaScriptFromString : というメソッドがあります。これは、JavaScriptを文字列で与えて実行するというもの。vWebがWebViewのインスタンスだとすると、

[ vWeb stringByEvaluatingJavaScriptFromString : @"(1+2)/4" ];

とすると計算結果が文字列で取得できちゃいます。似たような技として、NSAppleScriptを使ってAppleScriptを実行して結果を得るという方法もあります。

ただし、JavaScriptの場合、cosとかはMath.cosと書かないといけないのが若干面倒なものもあります。

ブラウザで表示したページの画像を自動的にスクラップ保存する

ブラウザで表示しているページの画像をあるサイズ以上のものを自動的にスクラップ保存してくという処理の実現方法の説明です。

画像などのダウンロード完了は個別に通知が来ますので、その通知が来た時に、キャッシュからデータを取り出してファイルに保存するというのが基本的な流れになります。

リソースのダウンロードが完了すると、WebResourceLoadDelegateの webView : resource : didFinishLoadingFromDataSource : メソッドが呼ばれます。3つ目のパラメータは、WebDataSourceのインスタンスなので、ここから受信データを取り出せそうな気が一瞬しますが、HTMLのページを受信しているときは、このWebDataSourceはHTMLのデータと関連づいているもので、画像を直接は取り出せません。

実は、パラメータにはリソースを識別するためのidしかないので、画像のURLを取得することも出来ません。このため、予めちょっとした仕込みが必要です。

リソースに識別子をつける処理 :
- (id) webView : (WebView *) sender identifierForInitialRequest : (NSURLRequest *) request fromDataSource : (WebDataSource *) dataSource { return( request ); // (1) リクエスト情報を識別子にする }

リソースのダウンロードを行う直前には、「リソースに識別子をつけるように」との通知が来ます。具体的には、WebResourceLoadDelegate webView : identifierForInitialRequest : fromDataSource : メソッドが呼ばれます。ここで、リクエスト情報をそのまま識別子として返すようにします。すると、ダウンロード完了時にリソースのリクエスト情報を受け取ることができるようになります。

リソースのダウンロード完了 :
- (void) webView : (WebView *) sender resource : (id ) identifier // ここにリクエスト情報が入ってくる didFinishLoadingFromDataSource : (WebDataSource *) dataSource { // (1) キャッシュからレスポンス情報を取り出す(レスポンスの中には受信データが入っている) NSCachedURLResponse *cResponse = [ [ NSURLCache sharedURLCache ] cachedResponseForRequest : identifier ]; NSURLResponse *response = [ cResponse response ]; // (2) MIMEが画像の場合のみ保存 if ( [ [ response MIMEType ] hasPrefix : @"image/" ] ) { // (3) レスポンスから受信データを取り出してNSImageにする NSImage *img = [ [ [ NSImage alloc ] initWithData : [ cResponse data ] ] autorelease ]; if ( img ) { // (4) NSImageが生成された場合のみ保存 NSImageRep *imgRep = [ [ img representations ] objectAtIndex : 0 ]; if (( 200 <= [ imgRep pixelsHigh ] )&&( 200 <=[ imgRep pixelsWide ] )) { // (4) 画像サイズの判定 NSString *sFoldPath = [ NSHomeDirectory() stringByAppendingPathComponent : @"Pictures" ]; NSString *sFilePath = [ sFoldPath stringByAppendingPathComponent : [ response suggestedFilename ] ]; [ [ cResponse data ] writeToFile : sFilePath atomically : YES ]; // ファイルへ保存 } } } }

キャッシュデータはNSURLCacheクラスで管理されていて、sharedURLCacheメソッドでインスタンスを取得できます。リクエスト情報を渡すとレスポンス情報を返してくれる cachedResponseForRequest : メソッドがあり、このレスポンス情報からキャッシュに記憶されている受信データを取り出すことが出来ます。

受信データが取れたらこっちのものです。レスポンス情報からはMIMEタイプも取れますし、画像のみを保存対象にするのも簡単。画像サイズの判定は、NSImageRepを使ってピクセル数を取得して行います。保存ファイル名は、レスポンス情報の suggestedFilename メソッドを呼ぶと、URLなどから決めてくれますので、これを使うとよいでしょう。

WebPolicyDelegateについて

WebPolicyDelegateとは、いくつかのWebViewの動作を事前に指示を行うデリゲートです。「 ページアクセスの直前 」「 レスポンスを受信後でコンテンツの読み込み直前 」「 新しいウィンドウを必要とするリンクジャンプの直前 」といった時に呼び出されます。デリゲートは、パラメータに渡される内容をチェックして、WebViewの動作を決めます。「 WebViewに読み込む/ダウンロードする/中止 」のどれかを指示することが出来ます。

ページアクセスの直前には、ユーザの操作やクリックしたリンクに関する情報や、ジャンプ先のURLの情報などが渡ってきます。そのため、例えば、「 特定のURLのページへのアクセスを制限する 」といったこともできますし、「 オプションキーが押されていたら、リンク先をダウンロードする 」とか、「 コマンドキーが押されていたら、リンク先を別ウィンドウで表示する 」といったことができます。

読み込み直前には、コンテンツのMIMEタイプが知らされますので、MIMEタイプによってそのまま読み込ませたり、ダウンロードさせたりということができます。例えば、zipやsitファイルのMIMEが来たときは、WebViewに表示させてもエラーになるだけですので、ダウンロードを指示します。

新しいウィンドウが必要な場合は、ユーザの操作やクリックしたリンクに関する情報や、ジャンプ先のURLの情報などが渡ってきます。シングルウィンドウのブラウザなら、「 新しいウィンドウを開かずに読み込むようにする 」とか、「 新しいタブを作ってそこに読み込ませる 」いったこともできます。

コンテンツを表示しているビューは何?

WebViewは、Webページを表示するための一番の親のビューですが、直接コンテンツは表示しません。WebViewの中には、各フレームを管理するWebFrameがあり、WebFrameはそのフレームを表示するためのWebFrameViewを持っています。このWebFrameViewも、まだ直接コンテンツは表示していません。読み込んだデータの種類に応じて使用するビューを切り替えるために、もう1つ下に子供を持っています。それがWebDocumentViewです。

このWebDocumentViewが、直接コンテンツを表示するビューになります。実際には、そのサブクラスであるWebHTMLView WebImageView、NetscapePluginDocumentView、WebTextViewのインスタンスが使われます。

考えてみればWebViewというのは非常に便利なものです。というのも、画像を表示したい場合、ファイルからNSImageを生成して、NSImageViewにセットする必要があります。動画ならファイルからNSMovie経由でNSMovieViewなどなど...。ファイルの種類に応じて処理の内容も用意するビューも違います。でも、WebViewなら、file://のURLを渡してあげるだけです。必要ならばスクロールバーも勝手に表示してくれます。編集はできないもののお手軽な万能ビューワといったところです。楽をするならWebViewを使ってしまうのも手です。