ページ

2008年4月11日金曜日

NSFormatter

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

前回 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];