さて NSValueTransformer、NSFormatter と検証して、その結果、バインディング値を任意の形式で表示させるには NSFormatterが良いことが分かったので、これを Windowリストへ組み込んでみる。
ソース:WindowList-3.zip
NSFormatterを組み込んだ結果、Boundsの表示が下の様だったのが
こういう風になった。
NSFormatter導入前は、NSCFDictionary の文字列表記(#description)の一行目が表示されていた。
{ <--ここだけが表示されていた
Height = 383;
Width = 740;
X = 625;
Y = 377;
}
今回 RectFormatterを導入して NSCFDictionaryに格納されている上記値をカンマ区切りで並べた文字列に変換するようにした。
RectFormatter.h
@interface RectFormatter : NSFormatter {
}
@end
RectFormatter.m
@implementation RectFormatter
- (NSString *)stringForObjectValue:(id)anObject
{
if (![anObject isKindOfClass:[NSDictionary class]]) {
return nil;
}
return [NSString stringWithFormat:@"%4d,%4d,%4d,%4d",
[[anObject objectForKey:@"X"] intValue],
[[anObject objectForKey:@"Y"] intValue],
[[anObject objectForKey:@"Width"] intValue],
[[anObject objectForKey:@"Height"] intValue]];
}
:
メソッド内のクラスチェックは重要で、最初これをやらなかったのでクラッシュした。理由はカラム値の初期値に InterfaceBuilderで設定された "Text Cell"が入っており、これが一番最初にこのメソッドに渡されるため。その結果 NSStringのインスタンスに対して #objectForKey: を投げることになったのでプログラムがクラッシュしていた。
クラス定義後に Interface Builder でインスタンス化してやり、目的の列(NSTextFieldCell)の fomatterアウトレットに接続する。
さらに今回は桁の表示位置を合わせたかったので等幅フォントを選び、サイズも 11ptと小さくした。これを行なう為に #attributedStringForObjectValue:withDefaultAttributes: を実装する。
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes:(NSDictionary *)attributes
{
NSString* str = [self stringForObjectValue:anObject];
NSFont *font = [NSFont userFixedPitchFontOfSize:11.0];
[attributes setValue:font forKey:NSFontAttributeName];
return [[[NSAttributedString alloc] initWithString:str
attributes:attributes] autorelease];
}
NSFormatterは初めて作ったが便利だ。アウトレットの接続だけで表示形式が追加できるとは Cocoaはよく考えられてるな。