« 2007年5月 | トップページ | 2007年7月 »

2007.06.29

KVO プロパティの遅延読み込み

feedbringer が止まってしまって、海外の Cocoa 動向がさっぱりなのだけど(手元の OPML のバックアップが古すぎて使えないというオチ)、ひさびさに Theocacao から。

"Lazy Loading of KVO Observed Properties" というエントリで KVO と KVC (おおざっぱに言えば Cocoa バインディング)で、あるキーの値の読み込みを遅延させる方法について例示されている。いわゆる Proxy パターン。この手法はアプリケーションで扱うオブジェクトがたくさんあるけれど、初期状態で要求される(たとえば画面に表示する)オブジェクトが少ないときなんかに有効。たとえば NSTreeController を経由して NSTreeView や NSOutlineView を利用するときなんかね。Theocacao の例で挙げられているのは、オブジェクトサイズが巨大というケース。

このテクニックを使うと、オブジェクトにデータ取得の役割(もしくはその役割をもつデータ生成機構への参照)を持つ必要があって、モデルオブジェクトがシンプルになりにくい。なんだか結局 delegate と同じような仕組みになってしまうなあ、ということをつらつらと考えた。

じゃあ Proxy オブジェクトか?Core Data の faulting なんかはそういうことだし。

|

2007.06.27

RubyCocoa 昨日のコミット(2007.06.26)

RubyCocoa 0.11.1 のバイナリパッケージが Mac OS X 10.4.10 にインストールできない件、みんな他のことで忙しいせいか、なんにも言われなかったのでリリースした。

0.11.1p1 というなんだかなバージョン番号としてダウンロードできるようになっています。報告してくれた人、ありがとう。

で、パッケージ作ったときに気がついたのだけど、これって rake doc で作成したドキュメント(ri)入ってるのな。ADC のリファレンスを加工したものなのだけど、これって配布して良いものなのかね?てか、これのインストール先があきらかにおかしい。インストールスクリプト直さなくちゃね。

|

2007.06.24

isEqual: 使ってる?

オブジェクト指向な言語では「等しい」という判定の方法が、対象のオブジェクトによって異なるというのが一般的で、Cocoa なら isEqual: メソッドがそれに該当する。[rubycocoa:0429] あたりのことから、Cocoa で isEqual: メソッドはどのくらい使われているか興味がわいたのでざっと調べてみよう。

ということで Google Code Search: 言語 Objective-C "isEqual:" で検索してみた。文字列の比較ばっかりだよ!今回知りたいのは文字列じゃなくって、一般的なオブジェクトのケースなのでこの結果はあまり参考にならない。

じゃあ、比較対象を sender に限定してみよう。これなら UI のオブジェクトだから、文字列ということはほとんどないでしょう。

思ったほど大差じゃなかったな。てか == も少ないなあ。

まあ sender になるようなオブジェクトなら tag つけとくのが Cocoa 的に正しいのかな。switch 使えるようになるし。ただ、IB で数値指定するのはイマイチだよな。 awakeFromNib で setTag: するなどコード側で初期化してやるのが順当かなあ。

|

2007.06.22

RubyCocoa 今日のコミット (2007.06.21)

  • Mac OS X 10.4.10 に バイナリパッケージがインストールできない問題を修正(r1853)

珍しく tracker に問題が報告されていた。マジごめん。この機能つくったときには、まさか 10.x.10 とか出ると思わなかったのだよ。許しておくれ。

許容するシステムバージョンを

  • 10.x 以上、10.x.9 以下

という条件から

  • 10.x 以上、10.(x + 1) 未満

に変更した。ロジックはかなりてきと〜。このへんのバージョン番号の操作にアタマ使いたくなかったから、「以下」で解決したかったんだけどなあ。

新しいパッケージリリースしたほうがいいとは思うのだけど、前回のリリース関わってなかったので単純に rake package すればいいのかわかんね。ML に相談中。

というか、インストーラに「10.4.8 以上」とか要求書いてあるけど、そうなんだっけ?

|

2007.06.20

ウェブブラウザによるページ内ナビゲーション

アイディアだけ。まだ1行もコード書いてない。

ある程度のボリュームのある HTML ページにはページ内の索引などの、ナビゲーションリンクが用意されていることが多い。もう今どきはまともにマークアップされたページがほとんどなので、そのページにナビゲーションが用意されていなくても、HTML から自動的につくることができるはず。

  1. ページの HTML から、Hn(1-2くらい?)要素を抜き出す
  2. ナビゲーション表示
  3. 選択されたアウトラインの位置へ移動

というような機能。

ちょっと探してみたらよさそうなのを見つけた。「ページ内ナビゲーション改善のためのアイデア」(Jakob Nielsen博士のAlertbox)がイメージに近い。Firefox プラグインあたりでもう実現されてるような気がするけど、ぱっと眺めた感じでは見つからず。ケータイのフルブラウザにはあるかも(知らない)。

プロトタイプつくろうとしたものの、アンカーがないときに 3. の移動の実装でストップ。もしかして JavaScript で要素の位置計算するしかないのか?URI の fragment に XPath 指定して移動とかできるといいのに。

少なくとも「上へ」とかいうリンクはいらない、ブラウザ側でできればいいのだから。現状でも home キーで問題ないし。とか考えていたら、話が飛んでいた、という話。

|

2007.06.19

php-gtk

なるものがあるらしい(PHP-GTK)。macports の ML で流れていた。glade に php コードが混ぜられるとか?そんなことしないか。

冷静になってみればそんなに驚くことでもないのだろうけど、なんか衝撃。

|

2007.06.12

Cocoa 入門サイト「Cocoa はじめの一歩」

Cocoa 勉強会のメンバーでもある関根さんが 「Cocoa はじめの一歩」 という Cocoa 入門のページを公開しています。プログラミング経験のない人向けの C言語のとっかかりから、Xcode/Interface Builder を使っての GUI アプリケーションの作成という構成。

「Become An Xcoder の翻訳をはじめた」と聞いてから数日でほとんど終わっていたのに驚いた(文章チェックできなくてゴメンなさい。今やってます)のだけれど、原文読んだときに「ちょっと説明足りないんじゃないかなあ」と思っていた、C言語のいくつかの構文についても補足していてナイス。

mkino さんの新刊もそろそろ出るみたいだし、Cocoa をはじめるしきいが低くなるといいなあ。

|

RubyCocoa の new を考える

RubyKaigi 自体の日記は書くの時間かかりそうなので、とりあえずこの件を先に。藤本さんのセッション中に irc でちょろっと出ていたけれど、RubyCocoa の Cocoa クラスにはインスタンスを生成する new メソッドがない。というかエラー。

 % irb -r osx/cocoa
 irb(main):001:0> OSX::NSURL.new 
 RuntimeError: use 'alloc.initXXX' to instantiate Cocoa Object
        from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/o
 sx/objc/oc_import.rb:251:in `new'
        from (irb):1

これは Ruby と Cocoa オブジェクトの初期化の手続きや、initXXX のそれぞれに対応して Object#initialize() を調整するのが手間がかかるってあたりが理由(だと思う)。

でも Ruby なら new したいよな。ただでさえ Cocoa のメッセージ名長いし。で、考えてみたのだけれど、欲しいところから順に CocoaClass.new を定義していけばよいんじゃなかろうか。正月にリファレンスマニュアルの作業してて、クラスメソッド new を定義してあるのを見たときは驚いたけど、定義したからって問題があるわけじゃない。

Hash をキーワード引数的に受け取るのがいいのかな。たとえば、

 class OSX::NSView
   # - :frame : ビューの位置、大きさを NSRect で 
   def self.new(args = {})
     args[:frame] ||= NSMakeRect(...) # 省略されたら適当な初期値を
     self.alloc.initWithFrame(args[:frame])
   end
 end
 
 class OSX::NSWindow
   # - :contentRect
   # - :styleMask
   # - :bufferingType
   # - :defer
   # - :screen
   def self.new(args = {})
     args[:contentRect] ||= NSMakeRect(...)
     args[:styleMask] ||= NSTitledWindowMask & NSClosableWindowMask &
                          NSMiniaturizableWindowMask
     args[:bufferingType] ||= NSBackingStoreBuffered
     args[:defer] ||= true
     args[:screen] ||= nil # メインスクリーン
     self.alloc.initWithContentRect_styleMask_backing_defer_screen(...)
   end
 end

こんな感じ。適切な初期値を考えるのがちょっと大変かもしれないけれど、引数の多い初期化メソッドが少なくない Cocoa では有効かもしれない。初期値が気に入らなければインスタンスを生成した後で、setter で値を変更すればいいだけだし。

|

2007.06.10

RubyCocoa on Ruby-1.9 の現状

rubycocoa-talk で聞かれたので、とりあえず試してみた。今日時点での trunk ruby-1.9 (12497)。

 % ruby19 install.rb config 
 install.rb:178:in `method_missing': private method `init' called for #<ConfigTab
 le:0x4a53a8 @table={}> (NoMethodError)
  from install.rb:178:in `new'
  from install.rb:856:in `execute'
  from install.rb:1131:in `<main>'

あうあう。1年くらい前はスレッドまわり直すだけでコンパイルまではとおったような記憶が…

まーがんばりましょう。

|

2007.06.08

そうだ、Gnome じゃなきゃいいんだ

rabbit のバイナリ .mpkg を作成すると、ファイルサイズがでかくなりすぎの続き。大きくなる理由は、Gnome 関係のファイルがたくさんあるから。じゃあ、ruby-gnome2-all じゃなくて ruby-gtk2 にすりゃいいのだ、と気づく(おせーよ!)。

ということで、rb-gtk2 というパッケージをつくって svn につっこんだ。これで作成した .mpkg が 25MB くらい。まあこれくらいなら納得できるサイズだな。依存パッケージ総数も 24 と、rb-gnome 時の 102 の 1/4 以下になったし。

rb-gtk2 内容の一部は rb-gnome と衝突する(はず)ので、両方はインストールできないことに注意。

  • ruby-gtk2 には含まれない機能 (RSVG とか) を使いたい
  • rabbit 以外で ruby-gnome2 が必要

というときは、以下のように rabbit に with_gnome の variant を指定してインストールしてください。内部的に依存関係を差し替えて処理します。

 % sudo port install rb-rabbit +with_gnome

|

2007.06.07

MacPorts の w3m 0.5.2 が重い

0.5.2 が出たので、なんの気もなく port upgrade w3m したらプロセスの開始がえらく時間かかるようになった。手元の環境では、いろんなとこで w3m 使っていて、そしてそのことを忘れているので、はじめはファイルシステムかなんか壊れたかと思った。調べるのがめんどい(たぶん image か nls あたりだろうけど)ので、重そうで使わない機能をおおざっぱに削除して再インストール。

 diff -ur /opt/local/var/db/dports/sources/rsync.rsync.darwinports.org_dpupdate_dports/www/w3m/Portfile www/w3m/Portfile
 --- /opt/local/var/db/dports/sources/rsync.rsync.darwinports.org_dpupdate_dports/www/w3m/Portfile	2007-05-31 22:31:54.000000000 +0900
 +++ www/w3m/Portfile	2007-06-06 01:31:28.000000000 +0900
 @@ -18,7 +18,9 @@
  depends_lib         lib:libgccpp.1:boehmgc
  patchfiles          gc_init.patch
  configure.args      --with-gc=${prefix} --with-ssl=${prefix} \
 -                        --enable-keymap=w3m --enable-image=x11 \
 +                        --enable-keymap=w3m --enable-image=no \
 +			--disable-nls --disable-xface --disable-bgcolor \
 +			--disable-nntp --disable-gopher \
		   --with-termlib=curses --mandir=${prefix}/share/man
  # libwc will not find gc unless ..
  configure.env       CFLAGS=-I${prefix}/include/

このへん variant ほしいなとは思うものの、どこまでやればいいのか見当がつかないという tiket をオープンしない言い訳。

|

RubyCocoa 0.11.1 リリース

出ました(rubycocoa-devel:947])。0.11.0 のバグフィックスが中心。SourceForge のファイルアーカイブ からダウンロードできます。

Laurent はじめ開発メンバーのみなみなおつかれさま。最近コード読み直しているけれど、内部もけっこう変わっているのね。

ついでに告知しておくけど、今週末の RubyKaigi 2007 でふじもとさんの RubyCocoa セッションもあります。RubyKaigi には、木村も参加予定(こちらは一般聴衆)なので、質問やリクエストあればてきとーに声かけてください。

|

2007.06.03

Rabbit 0.5.2 MacPorts も対応

Ruby/Gtk2 で書かれた素敵プレゼンテーションツール、Rabbit の新しいバージョン 0.5.2 がリリースされた([rabbit-shockers:282])ので MacPorts も対応。MacPorts での利用についてくわしくは Rabbit::INSTALL.macosx-macports.ja を参照のこと。

ひさしぶりにバイナリの .mpkg を作ったのだけど、サーバ側の QUOTA ではねられた。135MB はダメなのか。つーか、0.4 のときで 50-60MB くらいだったのにサイズ大きすぎない?と思ってユニバーサルバイナリが多いのかなあと調べてみたものの、そうでもなく。

じゃあ内訳ということで、.mpkg/Contents/Resources の個々のサイズを調べてみた。トップ 10 は次のとおり。

 % du -sk *.pkg | sort +0nr | head -10
 13028   perl5.8-5.8.8.pkg
 12764   python24-2.4.4.pkg
 11604   evolution-data-server-1.10.0.pkg
 9320    gtk2-2.10.11.pkg
 5648    nautilus-2.18.0.1.pkg
 4184    heimdal-0.7.2.pkg
 3872    ruby-1.8.6.pkg
 3680    openssl-0.9.8e.pkg
 3604    rb-rabbit-0.5.2.pkg
 3540    gettext-0.16.1.pkg

うーん、納得いかないサイズなのって evolution-data-server くらいか。0.4.1 のを引っ張り出してみると、パッケージ数が倍以上になってるなあ。ほしいのは gtk2 だけなので、python や gnome 環境いろいろはいらないのだけど、variant ちゃんと指定すれば抜けるのかなあ。

あきらめて、ディスクイメージファイルを 50MB で分割して再アップロード中。分割は hdiutil コマンドで。

 % hdiutil input.dmg -convert -format UDBZ -segmentSize 50m -o output.dmg

で、output.dmg, output.002.dmgpart, output.003.dmgpart, .. というように分割される。

|

2007.06.02

RubyCocoa 今日のコミット(2007.06.02)

0.11.1 リリース前のチェックで気がついた、サンプルまわりの簡単な手入れ。

  • sample/RubyAnywhere のコード部のテキスト入力欄(NSTextView)で書式の利用を不可に。他からコピペするごとに書式が変わるのがイヤだったので。(r1804)
  • sample/Scripts/sndplay3.rb を削除。検証で走らせていて、動作が sndplay2.rb と変わらないなあと思ってコードを見たら、定数とリテラルの違いしかなかった。どちらかだけあれば良いと判断。(r1805)

特に問題がなければ、来週の頭くらいにリリースが予定されています。気がついたことがあれば、早めにお知らせお願いします>みなさま

|

SandTrip 0.9.6 リリース - バグ修正、リダイレクト対応

WebKit なブラウザにローカル CGI 機能を追加する SIMBL プラグイン、SandTrip バージョン 0.9.6 をリリースしました。変更点は次のとおりです。

  • 応答ステータスをきちんと(つーか HTTP 応答じゃねえ!)
  • 301, 302, 303, 307 のときはリダイレクト先をブラウザに提示

なぜか CGI が HTTP プロトコルでステータスを返すと思ってしまっていた。テストもそれで書いたので、なんの確認にもなってないよ…

 # 誤 - 0.9.5 が期待していた出力
 HTTP/1.0 200 OK
 Content-Type: text/html
 Contennt-Length: 12345
  :
 
 # 正 - CGI が出力するヘッダ
 Status: 200 OK
 Content-Type: text/html
 Contennt-Length: 12345
  :

ついでにリダイレクトも実装。これはすっかり忘れてた。NSURL.URLWithString:relativeToURL: は文字列が相対パスじゃないとダメかと心配したけど問題なし。

 % irb -r osx/cocoa
 irb:001> url1 = OSX::NSURL.URLWithString("http://kimuraw.txt-nifty.com/d/")
 irb:002> url2 = OSX::NSURL.URLWithString_relativeToURL(
     "http://kirika.la.coocan.jp/proj/sandtrip/index.html", url1)
 irb:003> url2.absoluteString.to_s
 => "http://kirika.la.coocan.jp/proj/sandtrip/index.html"

さすがにそうじゃないとやってらんない。

|

2007.06.01

SandTrip 0.9.5 リリース - PATH_INFO 対応など

WebKit なブラウザにローカル CGI 機能を追加する SIMBL プラグイン、SandTrip バージョン 0.9.5 をリリースしました。

  • PATH_INFO 対応
  • HTTP 応答ステータスをきちんと
  • リロードによる環境設定の再読み込み

を実装しました。PATH_INFO に対応したので ViewVC など今までより多くの CGI ソフトウェアが利用できるようになりました。

もっとくわしく

指定された URL が、CGI として利用可能な拡張子(.cgi, .rb など)を含むとき、PATH_INFO として解釈されます。複数の拡張子を含むとき、最短のパスが実行ファイルとなります。

  • file://.../foo.cgi/bar/baz -> foo.cgi を実行、PATH_INFO は "/bar/baz"
  • file://.../foo.cgi/bar.rb/baz -> foo.cgi を実行、PATH_INFO は "/bar.rb/baz"
  • file://.../foo-cgi/bar.rb/baz -> foo-cgi/bar.rb を実行、PATH_INFO は "/baz"
  • file://.../foo.cgi/ -> foo.cgi を実行、PATH_INFO は "/"

もちろん、ディレクトリにこのような拡張子(に見える名前)がついていると正しく動作しなくなってしまいますので、注意が必要です。たぶん大丈夫だと期待。

HTTP 応答は今まで固定で 200 OK にしていましたが、ちゃんと出力結果に含まれる HTTP ステータスの値を返すようにしました。CGI 出力の先頭 5 バイトを見て、"HTTP/" なら CFHTTPMessageCreateEmpty() で空の CFHTTPMessage を生成します。そうでなければ、CFHTTPMessageCreateResponse() で応答ステータスを指定して CFHTTPMessage を生成します。後者の場合は、今までどおり 200 になります。(2007.06.01 まちがい!0.9.6 で修正しました)

こっそりと default.plist とユーザデフォルトの値をマージして読み込みするようにしたので、default write コマンドなどでデフォルトデータベースに設定値を保存しておくと、SandTrip のリビルドに影響されずに設定することができます。Property List Editor などで ASCII 形式の plist を作成しておいて

 % defaults write jp.nifty.i.kimuraw.SandTrip "`cat my_default.plist`"

などとするとよいでしょう。設定用の GUI はつくるつもりはありますが、まだありませんので。

今回のハマりポイント

NSURL#path は末尾の "/" を省略してしまうのにハマりました。困ったときの CoreFoundation で CFURLHasDirectoryPath() で判定。

 % irb -rosx/cocoa 
 irb:001> url = OSX::NSURL.URLWithString("file:///foo/bar/")
 irb:002> url.path.to_s
 => "/foo/bar"
 irb:003> OSX.CFURLHasDirectoryPath(url)
 => true

で、このときは "/" をもう一度追加して処理するようにしました。ってか、カテゴリで NSURL にメソッドを追加。

|

« 2007年5月 | トップページ | 2007年7月 »