アプリケーションで 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 でリンク先のページが開く。