もっともっと FontWell(その5)

(その4その3その2その1) すごい古い!2年近くぶりの続編。


今日、やっと BSFontWell の ibplugin 化のメドが立った。…遅すぎた!


なぜ、BSFontWell の ibplugin 化がいつまでも成されてこなかったか。それは簡単、「作れなかった」からである。作る必要はあった。なんといっても ibplugin を作らないと BathyScaphe の「表示」環境設定に対応する nib ファイルが開けない。もちろん、作ろうともした。ibplugin の作り方は深く考えだすとよくわからないけど、深く考えなければ数分で出来上がるレベル。しかし仮組みした ibplugin を Interface Builder でロードしてテストすると、すぐに例外を吐いて動作してくれない。途方に暮れて投げ出したままだった。


しかし、いつまでも「表示」環境設定の nib を開かないでいる訳にもいかないし、三連休の二日目だし。そして、なにより重要な手がかりを…Cocoa Binding を手がける人なら必ずチェックすべきこのページ、最近見に行っていなかったので気付くのが遅れたが、8/27 付けで追加されたトピックに発見したのだ!

If you implement a subclass of NSView and create an Interface Builder palette/plugin for that subclass, there are two important considerations for your implementation of the bind:toObject:withKeyPath:options: method: you must call super's implementation, and you should not call addObserver:... when your code is running in IB:

(中略)

If you call addObserver:... from bind:toObject:withKeyPath:options:, when your code is running in IB, IB may throw an exception and prevent you from establishing bindings. To work around this problem, you could conditionalise your call to addObserver:... by detecting whether you are running in IB, or you could conditionalise by using the preprocessor to remove the invocation of addObserver:... when building your palette/plugin.

"Bindings in an IB Palette - Cocoa Bindings Examples and Hints"

まさにドンピシャ、BSFontWell は確かに bind:toObject:withKeyPath:options: の中で addObserver:... を呼んでいる。それで上手く動かなかったのか…


かくして、Interface Builder 上で動作している時*1 は addObserver:... を呼ばないように修正した所、アッサリと ibplugin は動作するようになってしまった。細かい部分をもう少し仕上げないと恥ずかしくて公開できないけど、それが済んだら、あまりにも遅れたけれど、BSFontWell.ibplugin を公開します。


追記:…と、こんなタイミングで話題が微妙にクロスしてるのが、おもしろい。-[NSObject(NSKeyValueBindingCreation) infoForBinding:] は Mac OS X 10.4 からだけど、BathyScaphe ももう 10.3.x は知らんぷりだから、気兼ねなくこの方法に乗り換えても良い…!

*1: [ [ [NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.InterfaceBuilder3"] で判断してるんだけど、いいのかな?