アプリケーションで WebView を使う

Interface Builder でバインディングだけでスクリプトを書かないでも簡単なブラウザは作れてしまうけど、

ここでは、スクリプトを使っていろいろすることに関してメモしていく。

準備

まず、ib_outlet で @webView を指定する。

ib_outlet :webView

これを、Interface Builder で追加した Web View に結びつける。

ページを表示する

この Web View にウェブページを表示するには、setMainFrameURL(url) を使う。ここで、url は NSString なんだけど、

Ruby の String オブジェクトをそのまま使えるので、非常に簡単。たとえば www.apple.com を表示させたければ、

url = "http://www.apple.com/"

@webView.setMainFrameURL(url)

もしくは、

@webView.setMainFrameURL("http://www.apple.com/")

とやれば、Web View に Apple のホームページが表示されるはず。

ページの情報を得る

とりあえず、いくつか使ってみたことのあるものを並べてみる。

mainFrameURL ページの URL を得る

pageURL = @webView.mainFrameURL

mainFrameTitle ページのタイトルを得る

これは、ページの表示が終わらないとできない。あと、日本語の場合の文字コードの扱いが今一よくわからない。

pageTitle = @webView.mainFrameTitle

実際使うときは、ページタイトルを表示させたかったりするんだけど、ページを読み込み始めた時からページタイトルの情報が入ってきているかどうかはわからない。なので、webView_didReceiveTitle_forFrame(sender,title,frame) という delegate メソッドで、ページタイトルを受け取ったときにタイトルを表示するようにする。

次の例では、frame がページの Main Frame かどうかを確認して、そうであればタイトルを表示するようにしている。

def webView_didReceiveTitle_forFrame(sender,title,frame)

@webPageTitleText.setStringValue(title) if sender.mainFrame == frame

end

mainFrame.frameView.documentView.string ページのテキストを得る

pageText = @webView.mainFrame.frameView.documentView.string

これで、ページのメインフレームにあるテキストが抜き出せる。

mainFrame.frameView.documentView.attributedString ページのテキストやその他の情報を Attributed String として得る string では、単に文字としてテキストが抜き出せるが、attributedString を使うと、リンクなども一緒に取り出せる。イメージも取り出せるが、単に RTFDFromRange_documentAttributes を使って RTFD で保存すると開けないファイルが出来上がる。

pageText = @webView.mainFrame.frameView.documentView.attributedString

mainFrame.dataSource.representation.documentSource ページのソースを NSString として得る

pageHTML = @webView.mainFrame.dataSource.representation.documentSource

mainFrame.DOMDocument.documentElement.outerHTML これでもページのソースが NSString として取り出せる。

pageHTML = @webView.mainFrame.DOMDocument.documentElement.outerHTML

ページの情報を保存する

表示されているページを保存するには、これらを使ってデータを抜き出してから行う。とりあえずは、メインフレームのテキストを扱うことだけをメモしておく。それ以外の子フレームに関しては、メインフレームに対して childFrames というメソッドを使うと取り出せるので、それらに対して同じ処理をすればテキストが取り出せるはず。

ページのテキスト

まずは、ページに表示されているテキストをテキストファイルで保存する。

pageText = @webView.mainFrame.frameView.documentView.string

pageData = pageText.dataUsingEncoding(NSUTF8StringEncoding)

pageText.writeToFile_atomically(filePath,true)

ページのソーステキスト

次は、ページのソースを保存する。

pageHTML = @webView.mainFrame.dataSource.representation.documentSource

もしくは、

pageHTML = @webView.mainFrame.DOMDocument.documentElement.outerHTML

pageData = pageHTML.dataUsingEncoding(NSUTF8StringEncoding)

pageData.writeToFile_atomically(filePath,true)

この2つの例は NSString を NSData オブジェクトに変えてから writeToFile_atomically(path,true) で保存しているけど、もちろん NSString を直接 writeToFile_atomically_encoding_error(path,true/false,encoding,error) で保存してもいい。

pageText.writeToFile_atomically_encoding_error(filePath,true,NSUTF8StringEncoding,nil)

pageHTML.writeToFile_atomically_encoding_error(filePath,true,NSUTF8StringEncoding,nil)

ページのテキスト(書式情報付き)

ページの文字情報(フォント、スタイル)などを保持したまま RTFFromRange_documentAttributes(range,attributes) で NSData に変換して RTF 形式で保存する。

pageAttributedText = @webView.mainFrame.frameView.documentView.attributedString

pageData = pageAttributedText.RTFFromRange_documentAttributes([0.pageAttributedText.length],nil)

pageData.writeToFile_atomically(filePath,true)

WebArchive

もう一つ、表示されているデータを WebArchive 形式で保存する。まず、mainFrame で main frame を取り出して、dataSource で WebDataSource オブジェクトにする。そしたら、webArchive で WebArchive オブジェクトに変換して、それを data で NSData に変換してから保存する。拡張子は webarchive にする。

webDataSource = @webView.mainFrame.dataSource

archive = webDataSource.webArchive

archive.data.writeToFile_atomically(filePath,true)

JavaScript で開くウィンドウをそのまま表示する

アプリケーションを作ったとき、JavaScript で新しいウィンドウを開くリンクをクリックしても、新しいウィンドウを開かずにそのまま表示させたい場合は、webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener(sender,policy,request,frame,listener) という delegate メソッドを使う。

ここで、listener に新しいウィンドウを開くかどうか決めるためのオブジェクトが入っているので、ignore で無視する。request はその動作に対する request なので、リンクを開く動作の場合はそのページを開くものなので、mainFrame に対して loadRequest(request) というメソッドでその request を渡す。

def webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener(sender,policy,request,frame,listener)

listener.ignore

sender.mainFrame.loadRequest(request)

end

これで、JavaScript のリンクをクリックしても、そのままの WebView でリンク先のページが開く。