2011Takeba.mehttp://takebayashi.asia/に移転しました。このブログは今後更新されません。PagesHome2011-12-06ブログを新しくしました。2008のロジックボードを交換してもらいました。事の始まりは先々週の金曜日くらい。画面が乱れてフリーズするようになって、翌日には起動画面でフリーズするように。仕方ないので先週の火曜日に渋谷のジーニアスバーに。ここで再現しなかったら恥ずかしいなーとか思いつつジーニアスな姉ちゃんに見せると起動画面フリーズを見事に再現。外付けディスクから起動するとカーネルパニックを起こすオマケ付き。ジーニアスな姉ちゃんがいろいろ調べていくうちに、「GPUに問題がありますねえ」と一言。私「GPUっていったら......アレですね?」ジ「はい、アレですね」アレっていったら、NVIDIAが盛大にやらかしてくれたアレのことですよね。いうわけで、ロジックボードを無償交換してもらいました。先週の火曜日に預けて今日引き取ったので、ちょうど一週間。ジーニアスな姉ちゃんが「一週間くらいかかりますね」とか言ってたけどその通りでした。ハードディスクの中身もちゃんと残ってたし、時計がリセットされてたくらいで他は元通りのMacになって帰ってきました。"Safari"といったように(ofを使わない限りは)tell構文を使う必要がありました。Lionでも基本的にこれは変わりませんが、スクリプト全体を通してtell先のアプリケーションが同じ場合、スクリプト全体のtell先を指定することでtell構文を省略できるようになりました。application"ポップアップメニューを表示」というオプションを有効にします。application」というポップアップが現れるので、ここでアプリケーションを選択すると、スクリプト中でそのアプリケーションに対してtellする必要がなくなります。"applescript"だけでよくなります。NSTableCellViewという階層構造になっています。Builder上で直接さわれないようになっています。Builder上で設定するには、まずNSTableColumnの子(つまりNSTableCellViewと同じ階層)にカスタムビューを追加します。つぎに、追加したビューを選択し、インスペクタでクラス名をMyTableRowViewにします。IdentifierをNSTableViewRowViewKeyと設定すれば、カスタムクラスの設定は完了です。わかってしまえば簡単ですが、なんともわかりにくいような......。共有Lionでましたね。Diffを見て興奮したり、新APIのGuideを眺めたり、各所をclass-dumpして廻ったりしていると思います。Lionではついに念願のビュー・ベース・テーブルビューがサポートされました。要するに、今までテーブルの中身はセルじゃないといけなかったのが、ビューを突っ込めるようになったということです。これで「プログレスバーがテーブルビューに入らない!」なんて騒ぐ必要がなくなりますね。NSCollectionView使えば同じようなことできるけど、そんなの知りません。いうわけで、ビューベースのテーブルを作ってみましょう。Builderでxibを開き、適当なウインドウにテーブルビューを追加します。Basedを選択します。すると、NSTableColumnの直下にNSTableCellViewなんていうセルだかビューだかどっちなんだよって感じの名前のビューが追加されます。このビューがセルの代わりにテーブルコンテンツの表示を担います。Builderで適当にデザインしてあげましょう。ここでは画像とテキストを一つずつ表示するビューにしました。次に、テーブルビューのコンテンツを保持するNSArrayControllerを追加し、これに対してバインディングを設定します。NSTableViewのcontentをNSArrayControllerのarrangedObjectsにバインドします。注意したいのは、従来のセルベースのテーブルではNSTableViewではなくNSTableColumnをNSArrayControllerにバインドしてたんだけど、ビューベースではNSTableViewにバインドしなければならないという点です。次に、ビュー上のアイテムをバインドする必要があるわけですが、バインド先はNSTableCellViewにします。あとは、NSArrayControllerに適当なコンテンツを設定するよよう実装してビルドして実装すれば、ビューベーステーブルの出来上がり。webArchive];とすることでWebアーカイブを得ることができると書きましたが、これはOSXにおけるWebViewの話で、iOSのUIWebViewではそもそもWebFrameやWebDataSourceにアクセスできないのでこの方法ではWebアーカイブを取得できず、別の方法でやってやる必要があります。いうわけで、libxml2です。Webアーカイブはplistで、その構造もわかっているので、必要なのはWebページの周辺リソースを洗い出すことなわけですが、これをlibxml2でやってやります。libxml2はOSX/iOSの両方で利用でき、非整形なHTMLでもある程度パースできるので、XPathで外部リソースの在り処を探し出してplistにくるんでやれば一応Webアーカイブができ上がります。ちなみに今回は下の3つのXPath式で探すことにしました。//img[@src]//script[@src]//link[@rel='stylesheet'][@href]これで外部の画像、スクリプト、スタイルシートを探し出し、前回のエントリで紹介したフォーマットでアーカイブすれば完成です。一応動くものをGitHubに置いておきました。GitHubただしこの方法には欠点があって、HTML本体から直接参照されているリソースしか取得できません。img要素で埋め込まれている画像は取得できますが、CSSで指定されている画像は取得できません。要するに中途半端です。使いどころがないかといえば、そんなこともないです。CSSで画像を使った派手な装飾がされていなくて、テキスト中心で、たまに本文中に画像が埋め込まれてるようなページ(InstapaperとかInstapaperとかInstapaperとか)をアーカイブする時なんかには普通に有用な気がします。共有Safariで閲覧中のページを保存しようとしたとき、保存形式に「Webアーカイブ」ってのが選べますよね。そのページで利用されているリソース一式が1つのファイルを保存できる便利なアレです。CocoaでWebアーカイブを扱う方法そのWebアーカイブをCocoaで扱うには、WebKitのWerArchiveというドンピシャな名前のクラスを使います。次のようにすることでWebViewで表示中のページのWebアーカイブを取り出すことができます。dataというインスタンスメソッドを持っていて、そこで返されるNSDataオブジェクトをファイルに書き込むことでWebアーカイブファイルを作成することができます(拡張子を.webarchiveにすればSafariでちゃんと開けます!)。WebアーカイブファイルをNSDataとして読み込めば、そこからWebArchiveオブジェクトを生成してWebViewに読み込ませることができます。loadArchive:archive];Webアーカイブの中身Webアーカイブの中身はバイナリplistです。Editorにドロップしてみればちゃんと中身を見ることができます。plistということは、中の構造さえわかってしまえばWebKitを使わなくてもCocoaからあんなことやこんなことができちゃうわけです。いうわけでplistの内容をチェックしていきましょう。WebアーカイブplistのルートはDictionaryになっています。WebMainResourceDictionary。周辺リソースではなくそのページ本体について、以下のキーをもちます。WebResourceDataData。HTMLページの場合はそのHTMLをNSData形式にしたものが入ります。WebResourceFrameNameString。WebSubframeArchives絡み(後述)で使いますWebResourceMIMETypeString。text/htmlとか。WebResourceTextEncodingNameString。WebResourceURLString。その本体リソースが本来あったURL。WebSubframeArchivesArray。WebSubresourcesArray。ページに埋め込まれている画像やスクリプト等の外部リソースについて、(WebMainResourceと同じように)WebResourceData、WebResourceMIMEType、WebResourceURLのキーを使ってDIctionaryを作り、Arrayに追加していきます。SafariやWebKitが作ったWebアーカイブにはこれらの他にもリソース取得時のNSHTTPURLResponseインスタンスがWebResourceResponseというキーでアーカイブされているのですが、これを消しても正常に表示できるようなので、要調査。WebSubframeArchivesは、frame、iframe、objectといった要素で埋め込まれた外部ページのWebアーカイブをそのまま追加します。a.htmlの中のフレームにb.htmlが読み込まれている場合、a.htmlのWebアーカイブしようとする場合には先にb.htmlのWebアーカイブを作成し、その結果をこのWebSubframeArchivesのArrayの要素として追加する必要があります。このときのb.htmlのアーカイブは、さっきは空欄にしたWebResourceFrameNameにa.htmlでのフレーム名が入ります。おわりに上で見たように、WebアーカイブはただのplistなのでCocoaから簡単にいじることができるので、単なるファイル保存用途にとどまらず、いろいろな活用法があるかもしれません。CocoaじゃなくてもWindowsならCFLiteを使えば多分plistを扱えるとおもうので、ここはおひとつ試してみてはいかがでしょうか。Azure公認キャラクターのイラストやサンプルボイスが入手できるようになったことが一部で話題になってたりするので、せっかくなのでこのサンプルボイスをXcodeでのビルド完了時に自動的に鳴らすようにしてみましょう。手順1:MSDNからサンプルボイスが入ったzipをダウンロードして展開。手順2:Xcodeでビルド完了を通知したいターゲットを選んで「新規ビルドフェーズ→新規スクリプトを実行」を選択。{サンプルボイスへのパス}ちなみに33build.wavにすれば「ビルド完了!」って言ってくれる。作ったビルドフェーズは一番下においておく。こんな感じ↓あとは普通にビルドすれば、完了時に「ビルド完了!」ってお知らせしてくれます。......いや、だって、「ビルド完了」なんて言ってるボイスってこれくらいしか使い道がないじゃないですかこれ。Japanが東京電力の計画停電カレンダーを公開しました。Live用と書かれていますが、普通のWebCalなので他の対応アプリでも使用することができます。そこで、私が常用しているGoogleカレンダーで利用する方法を記しておきます。追加する」というリンクのURLをコピーします。Googleカレンダーにアクセスし、右下の「他のカレンダー」と書かれている下にある「追加」をクリックし、「URLで追加」を選択します。URLの入力欄が現れるので、さきほどコピーしたURLを貼り付け、「カレンダーを公開」をクリックします。以上の手順でGoogleカレンダーに停電予定を追加できます。(1)ブログを新しくしました。