ページ

2009年7月14日火曜日

ホットキー変更対応(26) - 修正2/キー変更時の一貫性

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

これまでのコードだと、ホットキー変更時の主導権が HotkeyTextView にあり、なんらかの理由でコントローラ側がキャンセルしようとしてもできない。実際のアプリケーションでは、コントローラが UserDefaults などに変更内容を保存(永続化)する。何かの理由でこの時に保存に失敗した場合は表示と保存値が食い違い、一貫性が保てなくなってしまう。

前回までのコードはこんな感じ。
HotkeyTextView.m

- (void)keyDown:(NSEvent *)theEvent
{
:
_hotkey.modifier = modifier;
_hotkey.code = keycode;

if (self.target && [self.target respondsToSelector:@selector(hotkeyShouldChange:)]) {

[self.target performSelector:@selector(changedHotkey:) withObject:self.hotkey];

// ↑この時点でコントローラがキャンセルしようとしてできない。
// コントローラが処理に失敗した場合でも、そのまま処理は続行されて
 // 表示は更新されたように見える。
}
:
}



コントローラのメソッド(上記では changeHotkey:)を一方的に呼び出すだけではなく、その戻り値を見て変更を続行するかどうか判断できるように修正する。今回は -[NSWindow windowShouldClose:] をお手本にして実装してみる。メソッド名も hotkeyShouldChange: としてみた。

UInt32 old_modifier = _hotkey.modifier;
UInt32 old_code = _hotkey.code;

if (self.target && [self.target respondsToSelector:@selector(hotkeyShouldChange:)]) {

_hotkey.modifier = modifier;
_hotkey.code = keycode;

NSNumber* result =[self.target performSelector:@selector(hotkeyShouldChange:) withObject:self.hotkey];

if ([result boolValue]) {
[self redraw];
[self endEdit];
} else {
_hotkey.modifier = old_modifier;
_hotkey.code = old_code;
}
}


変更前の値をとっておき(old_modifier, old_code)、hotkeyShouldChange: の結果を元に処理を行う。YESが帰ったらそのまま画面表示を更新して入力を終了する。一方 NO の場合は、変更前の値に戻して入力受付を続行する(見た目には何もおこっていないように見える)。

呼び出されるコントローラ側のメソッドでは結果に NSNumber のインスタンスを返す。
AppController.m
- (NSNumber*)hotkeyShouldChange2:(Hotkey*)hotkey
{
[_hotkey_register registHotkey:hotkey];
return [NSNumber numberWithBool:YES];
}

※上記はサンプルアプリなので UserDefaultsへの保存はまだ実装されていない。