XCode4でのnib編集時のTarget/Actionの扱い
以前のInterfaceBuilderで使っていたテクニックが使えなくなっていた。
InterfaceBuilderではtarget/actionパラダイムで接続出来るクラスは、以下の4つのメソッドがヘッダに定義されていれば問題なく使えた。
- (id)target;
- (void)setTarget:(id)anObject;
- (SEL)action;
- (void)setAction:(SEL)aSelector;
上記の4つのメソッドの有無で、IBActionConnectionでコネクションを張れるかどうかを判断していたらしい。
XCode4でこのテクニックは使えない。代わりに以下のような手法を使う。
actionセレクタを文字列で設定するメソッドを追加する
- (void)setActionName:(NSString*)inActionName { self.action = NSSelectorFromString(inActionName); } - (NSString*)actionName { return NSStringFromSelector(_action); }
ヘッダにtargetをIBOutletを付ける
@property (retain) IBOutlet id target;
XCode4上のUIエディターで通常のconnectionとして接続する事でtargetの設定が出来きる。
- XCode4上でセレクタ名を設定する
“Identify Inspector”の”User Defined Runtime Attributes”に
key Path actionName Type String Value <selectorNameString> と設定する。これで、nibの読込み完了時にactionが設定される。
メニューのアップデート
先日の問題の続き。
Application delegateで
- (void)applicationDidUpdate:(NSNotification *)notification
{
[[NSApp mainMenu] update];
}
と行えば、メニューの状態をメニューバーのクリック前に随時更新する。らしい。
NSLogで挙動を見る限り、更新作業をオンタイムで行っている。
が、ここで更に問題が有った。と言うよりも、私自身の問題認識が間違っている。
NSMenuは所有するNSMenuItemが全てDisableでもNSMenu自身はDisableになる訳ではない。
そもそも、OpenStepでは、MacOSの流儀と違ってSubMenuが選択出来ないからといって、Menuを選択出来ないようにする文化が無いのかもしれない。
NSMenuItemの更新のタイミング
NSMenuItemの更新のタイミング、[NSUserInterfaceValidations validateUserInterfaceItem:(id)anItem]が呼ばれるタイミングは、マウスがNSPopupMenuをクリックした時だった。
NSPopupMenuのmenuを表示する直前に更新処理をするのは、更新処理を必要最小限にする為と思われる。
理にかなっていると思うのだが、1点マズい事がある。
menuItemが全てDisableの場合は、NSPopupMenuもDisableにする必要がある。 しかし、更新のタイミングがNSPopupMenuをクリックする時だと奇妙な挙動が起る。
ユーザーが、NSPopupMenuをクリックした瞬間に、クリックしたNSPopupMenuがDisableに変わってしまう。(1/22追記 この認識自体が間違い)
解決方法は、更新処理をNSPopupMenuをクリックした時ではなく、NSWindowDidUpdateNotificationが飛んで来た時に更新すると良いと思われる。
コードは、色々と失敗したので挫折した。
Cocoa bindingが行われているかのチェック方法
[NSObject infoForBinding:バインディング名]で確認出来る。
nilで有ればbindingがされていない。nil以外の場合はbindingに関する詳細な情報がディクショナリ形式で返ってくる。