前回 NSValueTransformer を使ってバインディングした値の変換を行った。ただ NSValueTransformerは表現を変換するというよりは、値を別の単位や次元を変えるのが主な目的だと思われる。やりたいのは表現の変換なのでもう少し調べてみる。すると NSFormatter があった。前回と同じプログラムを今度は NSFormatterを使って実装してみた。
ソース:VTSample2.zip
まずは NSFormatterのサブクラスを作る。
HexFormatter.h
@interface HexFormatter : NSFormatter {
}
@end
HexFormatter.m
- (NSString *)stringForObjectValue:(id)anObject
{
return [NSString stringWithFormat:@"%x", [anObject intValue]];
}
- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
{
int num = 0;
int x =1;
int i = 0;
unichar ch;
for (i=[string length]-1; i >= 0; i--) {
ch = [string characterAtIndex:i];
if ('0' <= ch && ch <= '9') {
num += x * (ch - '0');
} else if ('a' <= ch && ch <= 'f') {
num += x * (ch - 'a' + 10);
} else if ('A' <= ch && ch <= 'F') {
num += x * (ch - 'A' + 10);
}
x *= 16;
}
*anObject = [NSNumber numberWithInt:num];
return YES;
}
@end
カスタムのフォーマッタを作る方法は ADCにマニュアルがある。
Creating a Custom Formatter
それによると3つのメソッドをオーバライドすべしと書いてあるが2つだけでも動作した。
まず #stringForObjectValue: は、わたされた値を希望する書式に変換するコードを書く。今回は10進数値を 16進数文字列に変換している。
次に #getObjectValue:forString:errorDescription: ではその逆に、入力された文字列を値に変換する。サンプルでは 16進数文字列を int値に変換している。
フォーマッタができたら、最後にこれを GUIのコントロールへ接続する。接続方法は InterfaceBuilder を使う方法とコードで書く2つの方法がある。サンプルでは InterfaceBuilderを使っている。
HexFormatterを InterfaceBuilderでインスタンス化しておいて、目的のコントロール(ここでは NSTextFieldCell)の アウトレット formatter へ接続する。
これで表示・入力する時にフォーマッタが適用される。
コードで接続する時はコントロールに対して setFormatter: を投げれば良い。こんな感じ。
HexFormatter* hex_formatter = [[[HexFormatter alloc] init] autorelease];
[cell_in setFormatter:hex_formatter];
[cell_out setFormatter:hex_formatter];