« 2006年9月 | トップページ | 2006年11月 »

2006.10.31

RubyCocoa - retain 漏れの探索 (その2)プレースホルダなんてあったね

RubyTypingTutor がクラッシュする件。[rubycocoa-devel:428]

ocm_retain_result_if_necessary() での alloc 時の振る舞いを変更すればクラッシュしなくなるってことは、Ruby 側からの alloc 呼び出しに関連した部分なんだろう。BigLetterView.rb での alloc は

 129     @attributes = NSMutableDictionary.alloc.init
 214     an_image = NSImage.alloc.init
  

の2箇所だ。これを alloc.retain.init に変更して試してみよう。その結果、 NSMutableDictionary.alloc.init にどうも問題があるらしいことがわかった。NSString など、このへんの Foundation の基本的なクラスの alloc 処理ってなんか特殊処理があったよな。あー、Cocoa のプレースホルダオブジェクトだ。

プレースホルダについては、mkino さんによる Objective-C optimization の翻訳「メモリ確保の基本と Foundation」 がわかりやすい。

RubyCocoa では、よりうまく利用できるように、0.4.2 から 0.5.0 にかけてメモリ管理モデルを変更した。新しいモデルは、ある Cocoa オブジェクトが Ruby 世界に出現するときには、Ruby の GC 用に retain するかどうかを判定し、必要なら retain、そうでなければ Ruby 側がオーナーシップを持つものとして、init での retainCount 1 を使うようにする。

で、今回はなにが問題かというと、プレースホルダを利用したクラスでは alloc 時と init 時に返してくるオブジェクト(Cocoa なら id 値)が異なることだ。すると RubyCocoa は、両方のオブジェクトについて「おまえらは Ruby GC の管理下だからな」ということで、マークする。このマークをつけられたオブジェクトは、Ruby から参照されなくなると、GC 時に release される。

今回のケースでは、

  1. alloc 時に プレースホルダにマーク
  2. init 時に 生成されたオブジェクトもマーク
  3. GC 時に プレースホルダは参照されていない(ふつう alloc.init と続けて書くので)から release される
  4. また同じクラスを alloc.init しようとすると、プレースホルダは dealloc されているのでクラッシュ

となってしまうわけだ。コードの修正はまたあとで。

|

2006.10.30

Keynote.app についての豆知識 - スムーズに見せるために

スライド内容じゃなくって、アプリの操作の話な。

MOSA Software Meeting 2006 のセッションで、スライド操作でいくつかもたもたしてしまった。最近は Rabbit ばかり使っていたというのがあるかもしれないけれど、反省を込めて、Keynote (現在 v3.0.2) でスライド操作をスムーズに行うために知っておくと便利そうなことをまとめた。

対象になるのは、基本はスライドで、ときどきデスクトップ操作もするっていうスタイル。

  • スライド表示 <=> デスクトップ操作(デモなど)の切り替え
  • スライド間の移動(単純な「次へ」以外の操作)

をスムーズに行うってのが主な内容。スライド操作時に「見せたいもの以外はできるだけ見せない」ことで、伝わる度が高くなるんじゃないかと。

キーボードショートカット

Keynote キーボードショートカット の「スライドショーを再生する」からピックアップ。

Option + 再生ボタン

スライドを最初のページから再生。Option キーを押しても「表示」メニューのほうは反映されないのがちょっと不便。

H - スライドを一時的に非表示に

デスクトップ操作をするプレゼンのとき必須。なにはともあれ、これだけは覚えておくべき。

デスクトップ操作が終わって、Dock のクリックや コマンド + tab で Keynote を再度アクティブにすれば、中断したところからまた再開される。この操作で非表示にしたとき、Dock 上の Keynote アプリケーションアイコンにグリーンの再生マークがつくので、それを探せばよい。

Esc キーで中断すると、もう一度再生開始の指示をしないといけないし、編集画面が見えてしまうのでちょっとカッコ悪い。

数字 - 指定ページへ移動

入力した数字のページがスライドスイッチャー(後述「よその情報」のアップルのページ参照)のジャンプ先候補に。Enter でそのページへ移動する。スライドスイッチャー上では、矢印キーで移動先候補の変更がもできる。説明の流れ上、ほかのページを表示したいときなどに便利。

でも、あらかじめ話の流れにそのページへのジャンプが計画されてるなら、スライド上のオブジェクトにジャンプ先ページへのリンクを仕込こんでおくのがよい。そうすれば、当日アタフタせずに済む。

Z - 前のページに戻る

ウェブブラウザの「戻る」機能のようなもの。スライドスイッチャーやリンクでページジャンプした後に、元のページに戻るときに便利。

ジャンプするときには、行き先は明確なので迷わないのだけど、戻るときはわからなくなってしまいがち。自分はしょっちゅうこのケースにはまる。ここで迷うと、時間を大きくロスしてしまうし、準備不足に見えて(確かにそうなんだけど、実際以上にそう見えてしまう)カッコ悪い。

] - ビルドを無視して次のページ

いくつか同機能のショートカットがあるのでお好みで。多数のビルドエフェクトがあるページから、ビルドをすっ飛ばして次のページにいくときに使う。

この機能を使うのはこんなときだ。Keynote の再生中にページ移動すると、移動先のページは初期ビルド状態になっている。Z - 戻る や、左矢印でうっかり戻りすぎたときに次のページへ進むためには、全ビルド分クリック / Enter しなくちゃ、というハメになる。つーかさ、1回のプレゼン中で既に表示したスライドは、最終ビルドの状態で固定されてほしいなあ。

C - カーソルを表示 / 非表示

ポインタカーソルを表示 / 非表示にする。基本は非表示にして、スライド上の場所を指すときにだけこの機能で表示させる、というのがお勧め。次のスライドにいくと環境設定の状態に戻るので、一時的に表示にした後に戻さなくても気にする必要はない。

スクロールホイール

これは積極的に利用するというより、気をつけるべきもの。スクロールホイールでは、数字の入力と同じようにスライドスイッチャーのモードになる。

これのなにが困るかというと、マウスクリックでスライドを進めていて、意図せずにホイールを触ってしまうと、当然スライドスイッチャーになるわけだ。予期しない動作だけにあわててしまう(自分がなった)が、落ち着いて Esc キーで戻ればよい。そもそも無効にできないもんだろうか…これ。

マウスクリックでの操作にこだわりがないのであれば、スライドを進めるのはスペースキーあたりのキーボード操作にするよう意識すると、この現象に出会わずに済むので安全だ。

Keynote では、control + ホイールの表示拡大機能は利用できないので注意。

環境設定

スライドショー > Expose や Dashboard などによる画面の使用を許可

チェック必須。次のようなメリットがある。

  • コマンド + tab で別アプリをアクティブにできる。ショートカットキー H いらず。
  • システム環境設定のユニバーサルアクセスで、ポインタカーソルを大きく設定してもちゃんと表示される。もとのカーソルは小さいので大きくしたいときに。
  • OmniDazzle のエフェクトが有効になる

OmniDazzle のエフェクトは Zoom が便利。どうしても文字が小さくなってしまうコード説明の際に、言及している場所を拡大すれば、相手に伝えやすい。

スライドショー > 最後のスライドの後でプレゼンテーションを終了

チェックをオフに。

好みの問題かもしれないけれど、最後のスライドの後にデスクトップが表示されて「ありがとうございました」となってしまうより、最後のスライドが表示されたままのほうがよいと思う。

その後の質疑応答になって「〜〜のところで」と質問されたらまたスライド表示する必要もあるわけだし。

発表者ディスプレイ > 発表者の情報表示用に別のディスプレイを使用

チェック。非ミラーで使えるハードウェアならやっておいた方がよい。ノートやコメントを使っていなくてもだ。スライドスイッチャーやムービーのコントロールなどが、発表者のディスプレイのみに表示されるようになる。

実行時間だけでなく、ふつうの時計も表示できるのがポイント高い。自分は発表時間(開始からの経過時間)より、終了予定時刻を目安にして残り時間で配分を考えながら話すほうがやりやすい。表示を残り時間にすると、なんだか急き立てられているようでペース早くなっちゃうし。

自分の設定ではこういう画面に。ほとんどデフォルトのままで、今のスライドを大きく、次のスライドを小さくしている。

ハードウェア構成によるのかもしれないけれど、発表者ディスプレイを別にしていると、ビルドエフェクトは省略されていきなり結果になる。もちろん、もうひとつのディスプレイではちゃんとアニメーションしている。

よその情報

スライドスイッチャーの画面を探していて見つけた、アップルの"医療ユーザのプレゼンテーション環境を革新するKeynote 2"がわかりやすくて良い。てか内容いくらかかぶってるよな。

(おわり)

|

2006.10.29

そろそろ、Cocoa Life Vol.3 の季節

そろそろ原稿に手をつけ始めないといけないかなあ。

今回は、今年の4月にやった「iTunes のような NSBrowser をつくる」をベースに、NSPredicate とコレクション演算子の機能で集合データを取り扱う方法について書くつもり。発表のときは、コントロールクラスとこれらの話をいっぺんにしようとして、方向が発散してしまったのを反省して、Cocoa の機能に絞り込んだ話にしよう。

Tiger では CoreData の導入により、集合データを扱うことが格段に容易になった。CoreData のパワーを有効に利用するためには、これらの Cocoa の機能を使いこなすこともわりと重要なポイントだと思うのだ。

まずは、今までどういった解説があるかを調べてみようと、木下さんの HMDT 3rd を読み直してみたところ、NSPredicate についてはほとんど語り尽くされているな。

ビジュアル中心での解説、というアプローチの差異で攻めることにしよう、うん。

しっかし、4月当時のスライドを消してしまったのでどういう話をしたのか思い出せない。

(2006/11/14 追記。原稿が十分に集まったため、今回自分の記事はナシになった)

|

RubyCocoa - retain 漏れの探索 (その1?)

[rubycocoa-devel:427] の話。まずひとつやっつけた。

RubyCocoa では、Ruby 用に 1 だけ retainCount を確保するようになっている。で、Cocoa のオブジェクトが Ruby 世界にあらわれたときに、この処理をするようにしている。ただし、alloc 直後など、オーナーシップの発生以前のオブジェクトは retain しないようにするべきだ。これが apple-unstable (昔の) で導入された改善のひとつだ。(see ocm_retain_result_if_necessary() in mdl_objwrapper.m)このおかげで "NSView not correctly initialized. Did you forget to call super?" はもう出なくなった。

この処理は Ruby から ObjC メソッドを呼び出して、Cocoa のオブジェクトが返ってきたときに行われるんだけど、ほかにもこの処理をしないとならないプロセスがあるんじゃないだろうか。

で、tutorial_1 の件はつかみやすそうなので考えてみよう。

このケースでは、retain されていないのは ib_outlets によって定義されたインスタンス変数だ。このオブジェクトは、nib の初期化処理によって生成され、アウトレットとして Ruby のコントロールクラスに渡される。すると、ObjC 世界から setXXX: の引数として渡されてるわけだ。待てよ、これって ruby 側からのメソッド呼び出しじゃないから、ocm_retain_result_if_necessary() の対象にならないよな。

というわけで、ObjC からの引数として渡すオブジェクトについて対処するようにした。(RBObject.m の diff)

|

trunk の問題点 まとめ

[rubycocoa-devel:425] の話。NSZombieEnabled アリガトウ という話?

今の RubyCocoa trunk では、以下の問題が見つかっている。

  1. sample/RubyTypingTutor で、ドラッグやコピー操作中にクラッシュする
  2. 藤本さんの MSM2006 の tutorial_1 で、特定の処理を評価するとクラッシュする

svn から、いくつか 0.4.3d2 以降の大きな変更のあったリビジョンを取り出して、検証したところ apple-unstable マージ後から発生するようなっていたことがわかった。

さらにもうちょっと細かく検証したところ、どうも両方ともメモリ管理まわりのようだ。

1. は alloc 時にも retain してやる(apple-unstable マージ前の動作)ようにすると、ちゃんと動く。

2. は ruby でインスタンス変数に代入しているオブジェクトが dealloc されてしまっている。これは、superview であるウインドウの contentView が破棄されるので、インスタンス変数への代入さえされていなければ、正しい動作だ。

どっちも NSZombieEnabled で試して見つけた。これがなかったらまず無理だったろう。

クラッシュは、たいてい EXC_BAD_ACCESS だ。これはその名のとおり、触ってはいけないメモリ領域にアクセスすると発生する。RubyCocoa なら、以下のパターンが多い。

  • dealloc されたオブジェクトにメッセージ送信
  • 正しくない ObjC <-> Ruby の型変換

NSZombieEnabled で例外が発生するようになれば、前者であることがほぼ確実になる。

調査はつづく。

|

2006.10.28

RubyCocoa 0.5.0 リリース延期のお知らせ

いくつかのサンプルが動作しない問題が確認されたため、0.5.0 のリリース作業は中断しています。開発チームで調査を続けていますが、現在のところ原因の特定にいたっていないため、解決には時間がかかるかもしれません。

とりあえず、お知らせまで。

個人的には、メモリ管理かオブジェクト変換のどちらかのような感触はあるのですが、推測にすぎず。

|

2006.10.25

まだ、RubyCocoa のユニバーサルバイナリが i386 で動かない

ダメだった…。3度目の正直なるかっ!?

ええと、0.4.3d2 は大丈夫だったんだよな。じゃあそれの setup 時の出力と比較してみよう。

てきとうに省略。

 (0.4.3d2)
 CompileC .o .m
 DynamicLibrary.LinkUsingFileList /Users/kimuraw/proj/rubycocoa/src/rubycocoa-0.4
 .3d2/framework/build/Default/RubyCocoa.framework/Versions/A/RubyCocoa /Users/kim
 uraw/proj/rubycocoa/src/rubycocoa-0.4.3d2/framework/build/RubyCocoa.build/Defaul
 t/RubyCocoa.build/Objects-normal/LinkFileList
     /usr/bin/gcc-4.0  -o /Users/kimuraw/proj/rubycocoa/src/rubycocoa-0.4.3d2/fra
     mework/build/Default/RubyCocoa.framework/Versions/A/RubyCocoa   "-L/Users/kimura
     w/proj/rubycocoa/src/rubycocoa-0.4.3d2/framework/build/Default" "-L/usr/lib"  "-
     F/Users/kimuraw/proj/rubycocoa/src/rubycocoa-0.4.3d2/framework/build/Default"  -
     filelist /Users/kimuraw/proj/rubycocoa/src/rubycocoa-0.4.3d2/framework/build/Rub
     yCocoa.build/Default/RubyCocoa.build/Objects-normal/LinkFileList  "-framework" "
     Cocoa" "-lruby.1"  "-arch" "ppc" "-dynamiclib" "-compatibility_version" "1" "-cu
     rrent_version" "1" "-undefined" "suppress" "-flat_namespace" "-arch" "ppc" "-arc
     h" "i386" "-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk"  -install_name "`ech
     o "@executable_path/../Frameworks/RubyCocoa.framework/Versions/A/RubyCocoa" | /u
     sr/bin/sed 's!//*!/!g'`"
 (svn trunk)
 CompileC .o .m normal ppc objective-c com.apple.compilers.gcc.4_0
 Ld /Users/kimuraw/proj/rubycocoa/src/framework/build/Default/RubyCocoa.framework
 /Versions/A/RubyCocoa normal ppc
     cd /Users/kimuraw/proj/rubycocoa/src/framework
  /usr/bin/gcc-4.0 -o /Users/kimuraw/proj/rubycocoa/src/framework/build/Defaul
  t/RubyCocoa.framework/Versions/A/RubyCocoa -L/Users/kimuraw/proj/rubycocoa/src/f
  ramework/build/Default -L/usr/lib -F/Users/kimuraw/proj/rubycocoa/src/framework/
  build/Default -filelist /Users/kimuraw/proj/rubycocoa/src/framework/build/RubyCo
  coa.build/Default/RubyCocoa.build/Objects-normal/ppc/RubyCocoa.LinkFileList -fra
  mework Cocoa -arch ppc -Wl,-single_module -compatibility_version 1 -current_vers
  ion 1 -install_name @executable_path/../Frameworks/RubyCocoa.framework/Versions/
  A/RubyCocoa -Wl,-Y,1455 -dynamiclib -undefined suppress -flat_namespace -arch pp
  c -arch i386 -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -lxml2 /usr/lib/lib
  ruby.1.dylib

これらを比較してみると、

  • CompileC では -arch ppc -arch i386 はついてる
  • リンク(DynamicLibrary / Ld) でも、-arch ppc -arch i386 はついてる

これだけ見ると問題なさそうだよなあ。

でも後者のリンク対象で、Objects-normal/ppc とかあるのがヤバそうだよな。対応するような i386 がないし。これまでの手順は Makefile ベースの手順 と同じようにしていた。でも、Xcode ネイティブのプロジェクトにしてるときは、それじゃあマズかったりするんじゃないだろうか?

というわけで、Xcode ネイティブの手順に従ってやってみよう。ビルド設定は次の2つだ。

  • ARCH = ppc i386
  • SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk

これらを設定したかわりに、CFLAGS と LDFLAGS の -arch と -isysroot, -libsysroot は不要になるね。これの setup 時の出力は

 (Xcode ネイティブに対応後)
 CompileC .o .m normal ppc objective-c com.apple.compilers.gcc.4_0
 Ld .build/Objects-normal/ppc/RubyCocoa normal ppc
 CompileC .o .m normal i386 objective-c com.apple.compilers.gcc.4_0
 Ld .build/Objects-normal/i386/RubyCocoa normal ppc
 CreateUniversalBinary RubyCocoa normal "ppc i386"

となる。ppc と i386 でそれぞれ RubyCocoa オブジェクトをビルドし、それを CreateUniversalBinary 時に lipo でファットバイナリにしている。

これでまたダメだと厳しいけど、ここまでくるともう「大丈夫」とは言えないよなあ。

どうでもいい知識が増えたような気がするけど、Xcode ではそれぞれのアーキテクチャ(このケースでは ppc と i386)でビルドフェーズを分けることによって、(BUILD_SETTING)_ppc といった形式のアーキテクチャごとの設定が利用できるようにしているんだろうな。gcc だけでも複数の -arch オプションを渡せば、一発で複数アーキテクチャのオブジェクトがコンパイル、リンクできるのだから。

|

推測 - RubyCocoa のユニバーサルバイナリが i386 で動かない

[rubycocoa-devel:402] の話。

ふつうにスクリプトでつくった RubyCocoa のユニバーサルバイナリのパッケージがどうもうまく動かないようだ。0.4.3d2 のときはちゃんと動いてたんだから、その後の変更があやしいよな。

というわけで、まずは setup 時の出力を見てみよう。

MasterObjectLink /Users/kimuraw/proj/rubycocoa/src/framework/ build/RubyCocoa.build/Default/RubyCocoa.build/Objects-normal/ RubyCocoa-ppc-master.o

なんだか見たことない出力が。これのどこがあやしいかっていうと、ppc だけでi386 に関する出力がないんだよな。この master.o の i386 向けのオブジェクトが作成されていないために、intel Mac で動いていないんじゃなかろうか。

これは比較的最近にいれた Xcode のオプション GENERATE_MASTER_OBJECT_FILE がバツグンにあやしい。試しにこれを無効にして、再度 setup してみよう。

すると、上記の MasterObjectLink のプロセスがなくなった。前後の処理を見ても、これでよさそうな感じ。けっこう自信あるので ML にも "believe" とか思わず書いてしまった。

(2006/10/25 追記: そんなこと言っても、だめなものはだめなのだ。つづき

で、これで解決したらどうするかってことを考えた。以前にも書いたように、GENERATE_MASTER_OBJECT_FILE は .a な libruby で RubyCocoa を構築するためには必要なので、単純に削ってしまうと、あとで「ビルドできないっすよ」という問い合わせに対応しなくちゃなんなくなるので残したい。なので、libruby が .a のときのみ GENERATE_MASTER_OBJECT_FILE を YES にするようにパッチを書いた。

|

2006.10.24

このサイトが NOINDEX, NOFOLLOW になっていた

なんだか自意識を差し引いても、検索にひっかからなさすぎると思ったのでトップページのソースをみてみたら、head に

 <meta name="robots" content="noindex,nofollow" />

とかはいってやんの。調べてみたら、ココログの設定で「更新通知」を「いいえ」に設定するとそうなるらしい。ヘルプの説明だと、ココログのトップにでてくるかどうかにしか読めねーってば。

「はい」にして全ページを再構築した。

|

2006.10.23

RubyCocoa 今日のコミット

  • NSArray#to_a.each をボクメツ

RCArrayAttachment のおかげで、0.4.3d2 から NSArray#each が使えるようになっていたので、それを利用するように変更。ちょっとコードがすっきりに。

コミット前に update (svk pull) しなかったおかげで藤本さんとコンフリクトした。油断してた。

|

RubyConf 2006 "Leveraging Mac OS X from Ruby" by Laurent Sansonetti

Web 上のレポートをチェック

藤本さんの OSM の記事でも思ったけど、RubyOSA はかなりおもしろそう。Automator アクションも書けるはずだし、AppleScript であるがゆえに敬遠していた層を取りこめれば、RubyCocoa 以上に普及しそうな目はあるよな。今は svn からしか入手できないけど。

(2006/11/03 追記。10/26 に 0.1.0 が公開されている

型変換のパフォーマンス向上を目的とした、Ruby 組み込みクラスの置き換えについては、以前の Laurent の話だと、String / Array / Hash といったよく使うクラスをCoreFoundation ベースで Ruby のクラスを実装すれば、Cocoa へも toll-free bridge でウマウマ!というモクロミだった。聞いたときは RegExp 以外は問題ないんじゃないかなあ、と思った気がする。RegExp も 1.9 の正規表現エンジンの Oniguruma をベースとした OgreKit もあることだし、そういう点では心配ないのかもしれない。

さいごにちゃちゃ。2人とも「Tiger では 1.8.4」て書いてるけど、Tiger は 1.8.2 だったような。Laurent が間違ってしゃべったんかな?

 % /usr/bin/ruby -v
 ruby 1.8.2 (2004-12-25) [powerpc-darwin8.0]

(以下 2006/11/14 追記)

まつもとさんと Laurent の話で、キーワード引数のあたりについて。

キーワード引数のメリットてのは

  1. コードを見たとき、引数の意味がわかりやすい
  2. 引数を省略できる
  3. 順番を気にしなくて良い

ということだと考えている。Objective-C のメソッドにマッピングするためには、

  • 順番が重要(変更できない)
  • すべてのキーワードを指定する必要がある

の 2点を満たす必要があるため、メリットとして残るのは 1. だけだ。そうなってくると、もうなくてもいいかなとも思うし、Ruby のキーワード引数の(将来の)仕様と折り合いをつけるのがなかなか難しいんじゃないかと、悲観的な予測をしている。

|

0.5.0 準備完了っ!

ドキュメントの更新やら細かい修正やらが終わった。あとは開発メンバーで簡単な確認をしたらリリースするつもり。

リリース前に試してみたいひとは、現在の svn trunk をチェックアウトしてください。

知らなかったんだけど、Info.plist を Cプリプロセッサにかけられるんだね。これは便利だな。たぶん Jonathan が RubyCocoa のプロジェクトファイルを .xcodeproj に変えたときにそうなったんだな。

|

2006.10.22

宿題その2 - プロジェクトテンプレートをXcodeネイティブに

RubyCocoa の Application と Document base Application のプロジェクトテンプレートが Project Builder のまんまだったので、Universal Binary がつくりにくいというので変換した。

はじめは Xcode 2.0 にしようと Tiger の DVD 引っ張り出したんだけど、これって .pbproj じゃん。なので思い切って 2.2.1 のテンプレートから作成した。.xcodeproj になったので、Xcode 2.0 以前では利用できないのだけど、それはテンプレートを別途配布することで解決するつもり。

宿題おわり。

|

宿題その1 - eval でメソッドをオーバーライドしても反映されない

MSM2006での宿題 1/2。メソッドキャッシュなのかなあと思って検証。

 require 'osx/cocoa'
 
 class Foo < OSX::NSObject
   def foo(sender) 111 end
 end
 
 obj = Foo.ocm_send(:alloc).ocm_send(:init)
 p obj.ocm_send(:foo, nil).to_i
 
 class Foo < OSX::NSObject
   def foo(sender) 222 end
 end
 
 p obj.ocm_send(:foo, nil).to_i

出力は

 111
 222

と正しく動いている。べつに1回目の呼び出しでキャッシュされてるわけでもなさそう。

でよく考えてみると、eval に渡している binding がマズいのではと気づく。これは TOPLEVEL_BINDING じゃないとユーザの意図した動作にならないのは?

 --- WorksheetController.rb.org	2006-10-22 13:51:26.000000000 +0900
 +++ WorksheetController.rb	2006-10-22 13:51:42.000000000 +0900
 @@ -28,7 +28,7 @@
  
    def evaluate(sender)
      src = @scratchText.string.to_s.gsub(/\r/, "\n")
 -    result = with_io_redirect { eval(src, $binding) }
 +    result = with_io_redirect { eval(src, TOPLEVEL_BINDING) }
      @resultText.setString(result.inspect)
      @resultText.setTextColor(STD_COLOR)
    end

この修正で正しく動くはずで、RubyCocoa の問題ではないです>藤本さん

|

2006.10.21

RubyCocoa 今日のコミット

  • lib/ruby 側の osx/appkit.rb と osx/foundation.rb が修正されてなかったのを修正
  • obj.objc_methods にも 引数を追加。false が渡されたときはスーパークラスを見ないように。(ruby 1.8 の methods と同じ仕様に。objc_class_methods と objc_instance_methods はそうしていたのだけど、objc_methods はそうなってなかった)
  • ドキュメントひたすら更新

ドキュメントの更新はほぼ完了。あとは配布ファイルのURLを直すとかくらい。それはまだできないからね。

MSM2006 で藤本さんと話しているときに、宿題が2つばかりできたのでそれが残作業に。それが終わったら、テストして、リリースできるはず。

|

MSM2006 行ってきた

例によって資料を置いておく。スライドのみ。ちょっと時間足りなかったところは反省。

どうせ質問がでるだろうとスキをつくっておいたけど聞かれなかったので、資料に載せなかった個人的な見解。

Q. OpenDoc とか「発行と引用」の歴史があるんだけど大丈夫?

A. Appleが提供したモジュールではなくってオープンソースの フレームワークであること、Cocoaのクリップボードや分散オブジェクトといった 基本機能を利用してい構成されていることから、使えなくなるという 状況は発生しにくいと考えている。 ただ、Appleのお墨付きがないことで普及が遅いってデメリットもあるけれど。

参加してくれたみなさん、協力してくれたスタッフの方々、ありがとうございました。

|

2006.10.18

NSURLProtocol サブクラスの canInitWithRequest: は登録の逆順に呼ばれる

経験的にそうであることは知っていたけど、ドキュメントには書いてないからねえ、と思っていたのだけど、webkitsdk-dev ML で Apple の人がそう言っていたから仕様だと思っていいのかな。

SandTrip はそうであることを利用して file: スキームの特定の URL を横取りしてるわけなので、今後もそのへんは大丈夫なようだ。ひと安心。

参考:URL Loading Systemを拡張する (Cocoa 勉強会の昔の発表)

|

RubyCocoa 今日のコミット

0.5.0 のリリース準備。

  • 今年になってから追加されたサンプル(from rubycocoa.com) の中に ns_overrides があったので削除。
  • ドキュメント類の最低限の更新(まだ途中)

勢いさえつけば作業はできるのだ、と改めて実感。できるだけ早くリリースできるよう努力しまっせ。Laurent がブランチを早くマージしたいみたいだしね。

|

2006.10.17

OmniDazzle を Keynote で有効にする

OmniDazzle のエフェクトが Keynote 上で描画されない。ウインドウレベルの関係かなあとおもっていたら、ふつうにヘルプに書いてあった。

Keynote の環境設定で「Expose や Dashboard などによる画面の使用を許可」 にチェックをつけたまえ

ユニバーサルアクセスでポインタカーソルを大きくすると、Keynote 上で見えなくなってしまうのも、同じ理由っぽい。両方解決してシアワセ。

|

2006.10.16

今週末は RubyCocoa 祭りだ!

両方に参加するのはまず不可能という、ワールドワイドっぷり。

ちょっと前に発売されたオープンソースマガジン 11月号に藤本さんによる RubyCocoa の記事も掲載されるなど、なんか一気にいろいろきた感じ。

ということで政治的パフォーマンスとして、svn trunk を 0.5.0 としてリリースしてしまうのはどうだろうか。まだ変更点をまとめ終わってないのが問題だけど。

|

2006.10.15

MSM2006 発表練習

Cocoa勉強会の有志で、MOSA湘南ミーティングのセッションリハーサル。協力してくれたみなさん、ありがとうございました。

自分のは時間はだいたいOKで、後半がわかりにくかったので構成を見直し。やった甲斐があった。

|

2006.10.14

Rabbit の svn trunk 用 port

をコミット[rabbit-shockers:235]。svn.tag のところを HEAD にすれば常に最新になるとは思うけど、パッチもあるし簡単だけど動作確認もしといたほうがいいしね。

今の 0.4.2 の Portfile につけてるパッチは、3種類くらいの修正を1ファイルにしてるので、本家に取り込みされたときに外すのがめんどいことに気づく。最初から要件別のパッチにしときゃよかった。

|

2006.10.04

Pragmatic Programmers の TextMate 本

「TextMate : Power Editing for the Mac」という本がでるそうだ。スゲエ!って BETA PDF はもう出てる。

via Samurai Coder

|

mogenerator で CoreData のカスタムクラスコード生成

rentzsch.com の "mogenerator: Core Data codegen" で、mogenerator というツールが公開されていた。これは WebObjects にあった EOGenerator というツールの CoreData 版(のようなもの)らしい(WO 知らないのでよくわからん)。コンパイルするには、MiscMerge.framework が必要。

これに CoreData のモデルファイル (.xcdatamodel) を食わせると、{_Foo.h, _Foo.m, Foo.h, Foo.m} といった 4つのファイルを生成する。で、Foo.h や Foo.m に自分の書きたいビジネスロジックを書けばよい。モデルに変更があっても、更新されるのは _Foo.h や _Foo.m だから影響しない。

これが、ジェネレーションギャップパターンによるものなのだけど、Objective-C なら_Foo に相当する中間クラスがなくって、カテゴリでアクセサが定義されてても問題がないと思う。Foo 側がクラス定義文でないとインスタンス変数が書けないので、_Foo 側がカテゴリになるね。

 // Foo.h
 @interface Foo : NSManagedObject
 // write custom logic
 @end
 
 // _Foo.h
 @interface Foo (GenerationGap)
 // accessors
 @end

そんなことよりなにが収穫かっていうと、去年探してた MiscMerge を見つけたってことなのだ。こんなところに!

|

2006.10.03

RubyCocoa thread 対策パッチを更新

以前に Jonathan がつくったパッチを、ruby-1.8.5 と rubycocoa svn trunk に合わせて更新した [rubycocoa-devel:388]。ruby の Thread クラスに手を入れて、RubyCocoa と協調するようにしたもの。

patch コマンドがほとんど調整してくれるから、更新したって言っても自分で積極的に手を入れたの一箇所だけだけど。

|

2006.10.02

svk patch まとめ

「svk patch って?」 の続き。cpan の SVK::Command::PatchSVK::Command::SmergeSVK::Command::Push あたりを読んでるうちにようやく理解できた。

概要

svk patch は、以下の2種類のファイル群の差異をパッチとして管理することができる。差異をとる対象として、次の2種類がある。

  • svk リポジトリ間。たとえば、//mirror/proj と //local/proj
  • svk リポジトリと作業コピー。//local/proj と それをチェックアウトしたもの

前者のパッチの作成では svk smerge (または push) コマンドを利用し、後者では svk commit コマンドを利用する。

こうして svk リポジトリ内に作成したパッチは、パッチに関するメタデータを持っている。それにより、--regenerate や --update オプションを利用してパッチ内容の更新を行うことができることが最大の特徴。ただし、ローカル側が作業コピーのときは、--regenerate は実行できないことに注意。

実演

以下の環境で試した。

  • svk-1.08
  • zsh

作業用の depot をつくる。

 % export SVKROOT=$HOME/tmp/.svk
 % svk depotmap /svkpatch_test $SVKROOT

検証の作業環境を作成。

 % mkdir test
 % gseq 10 > test/numbers
 % svk import -m "initial import" test //local/test
 % rm -rf test
 % svk co //local/test test
 Syncing //local/test(/local/test) in /Users/kimuraw/test to 2.
 A   test/numbers
 % cd test
 % cat numbers
 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 % 

テキストを変更して、パッチをつくる

 % vi numbers
 % svk diff
 === numbers
 ==================================================================
 --- numbers	(revision 2)
 +++ numbers	(local)
 @@ -1,5 +1,5 @@
  1
 -2
 +two
  3
  4
  5
 % svk ci -m "2 -> tow(en)" -P num2en
 Patch num2en created.
 % svk stat
 M   numbers

パッチを commit コマンドで作成しても、パッチのみがリポジトリに作成され、変更はコミットされない。

パッチが作成されたことを確認。

 % svk patch --list
 num2en@1:
 % svk patch --cat num2en
 ==== Patch <num2en> level 1
 Source: [No source]
 Target: f920d2e2-3b84-41a3-8411-0dd0c30360b6:/local/test:2 [local]
 Log:
 2 -> tow(en)
 === numbers
 ==================================================================
 --- numbers	(revision 2)
 +++ numbers	(patch num2en level 1)
 @@ -1,5 +1,5 @@
  1
 -2
 +two
  3
  4
  5
 % ls $SVKROOT/patch
 num2en.patch

作業コピーを編集して、パッチを再作成する。

 % vi numbers
 % svk diff
 === numbers
 ==================================================================
 --- numbers	(revision 2)
 +++ numbers	(local)
 @@ -1,7 +1,7 @@
  1
 -2
 -3
 -4
 +two
 +three
 +four
  5
  6
  7
 % svk patch --regen num2en
 Source of patch num2en not updated or not local, no need to regen patch.

むむ。ローカルがリポジトリじゃないと --regen はできないようだ。

リポジトリを変更して、パッチを更新する。

 % svk revert -R 
 Reverted numbers
 % vi numbers
 % svk diff
 === numbers
 ==================================================================
 --- numbers	(revision 2)
 +++ numbers	(local)
 @@ -1,3 +1,4 @@
 +0
  1
  2
  3
 % svk ci -m "add zero"
 Committed revision 3.
 % svk patch --update num2en
 G   numbers
 % svk patch --cat num2en
 ==== Patch <num2en> level 1
 Source: [No source]
 Target: f920d2e2-3b84-41a3-8411-0dd0c30360b6:/local/test:3 [local]
 Log:
 2 -> tow(en)
 === numbers
 ==================================================================
 --- numbers     (revision 3)
 +++ numbers     (patch num2en level 1)
 @@ -1,6 +1,6 @@
  0
  1
 -2
 +two
  3
  4
  5

パッチの内容も更新されている。作業コピーはここではリポジトリと差がないのだが、それは関係ない。内容的には、現在のupstreamリポジトリとパッチ作成時の作業コピーの差分がパッチとして更新されることになる。

ここで利用したコマンドのまとめ

  • svk commit -P : パッチを作成する
  • svk patch
    • --list : パッチの一覧を表示する
    • --cat (--view) : パッチの内容を表示する
    • --regenerate : ローカルの変更を作成済みのパッチに反映する
    • --update : リポジトリ(upstream) の変更を作成済みのパッチに反映する

じゃ残りのコマンド

 % svk patch --apply num2en
 U   numbers
 % svk diff 
 === numbers
 ==================================================================
 --- numbers     (revision 3)
 +++ numbers     (local)
 @@ -1,6 +1,6 @@
  0
  1
 -2
 +two
  3
  4
  5
 % svk patch --rm num2en
 % svk patch --list 
 % 

パッチは $SVKROOT/patch に作成されるんだけど、これだとプロジェクト共通になってしまう。階層化できるか試してみよう。

 % svk ci -m "2 -> tow(en)" -P test/num2en
 Illegal patch name: test/num2en.

うーむ。残念。

まとめというか感想

開発スタイルとして以下の2つのタイプがある。

  • svk commit -P: trunk を開発主体とし、作業コピーとのパッチをつくる
  • svk smerge -P: 修正ごとのブランチを作成し、trunk へのパッチをつくる

もちろん、両方を併用しても問題はない。大きな変更でブランチを作らないのは冒険でしかないわけだし。

簡単な修正のためにブランチをつくるのはわずらわしい、でもパッチはリポジトリに保存しておきたいっていうときに便利だと思う。

機能的にちょっと足らないかなあと思うところがなくもないけど、あとは実際の開発で使ってみての評価をするってことで。

|

第20回 Cocoa勉強会 に行ってきた

今まで最大の人数、っつーかもう誰が誰だかわからん。発表の中でも特におもしろかったもの。

松本さんによる、OpenMenu X の対応アプリケーションを増やすための工夫。まずはスタンダードな方法をとりつつ、漏れてしまう部分をカバーしていく方法について。スマートな実装で、カッコイイ。自分も書くならああいう実装にしたいもんだ。アクセシビリティAPI はそういう使いかたもできるのか。ちょっと掘り下げてみたいな。

大箭さんによる Growl プラグインの作り方。まずは例によってサンプルが笑える。WebKit スタイルのプラグインは、Growl 本体側の実装がどうなっているかが気になるところ。

うちゃさんの QuartzComposer の QCView をアプリケーション側から操作する方法もいい。質問でもでたけど、qtz を動的に差し替えるにはどうしたらいいんだろ?やっぱり QCView を一度捨てないとだめかなあ。

吉川さんの CoreData の限界に挑戦!は、ついに 25,000,000 件の格納まで到達。SQLite 自身はそのくらいまでいけることはわかっているので、CoreData で利用されるメモリをどのタイミングでどうやって解放するかっていうのがキモ。今回で CoreData の faulting まで解決したので、もうカベは残ってないんじゃないだろうか。

次回は今のところ 12/2(土) の予定。詳しく決まったら改めて告知の予定。

|

« 2006年9月 | トップページ | 2006年11月 »