読者です 読者をやめる 読者になる 読者になる

KOYAMA Yoshiaki のブログ

プログラミングについての試行錯誤をつらつら書き溜めていきます。

NSValueTransformer

雑談 プログラム mac

ADC *1をさまよっている時に OCUnit という単語が目に付きました。興味があったので ADC で検索し

Test Driving Your Code with OCUnit
http://developer.apple.com/tools/unittest.html

ページを見つけました。解説のサンプルとして

/Developer/Examples/AppKit/TemperatureConverter

を利用しています。

元のTemperatureConverter を変更したくないので TemperatureConverter フォルダをコピーして適当な場所にペーストし、動作を確認しました。

OCUnit を試すつもりだったのですが、TemperatureConverter を理解しないと先に進めません。(今回は時間がなく OCUnit は試すことができませんでした。 )

そこでソースを覗いてみました。NSValueTransformer を利用しています。私は NSValueTransformer をよく理解していませんでした。ソースや Interface Builder でバインディングを調べてみるとだいたい理解できました。

確認のために

Value Transformer Programming Guide
http://developer.apple.com/documentation/Cocoa/Conceptual/ValueTransformers/index.html#//apple_ref/doc/uid/10000175i

NSValueTransformer Class Reference (Objective-C)
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSValueTransformer_Class/index.html#//apple_ref/doc/uid/TP40003766

を読みました。TemperatureConverter の動作を理解した後なので、わかりやすかったです。

ただ Available Value Transformers の

NSNegateBooleanTransformerName 
NSIsNilTransformerName 
NSIsNotNilTransformerName 
NSUnarchiveFromDataTransformerName 

をどう利用すれば良いのか理解できませんでした。

Xcodeフレームワーク内を NSNegateBooleanTransformerName 検索してみると

/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSValueTransformer.h

FOUNDATION_EXPORT NSString * const NSNegateBooleanTransformerName AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;

と宣言されています。

NSLog(@"%@", NSNegateBooleanTransformerName); 

を実行してみると NSNegateBoolean と表示されます。NSNegateBooleanTransformerName の指す文字列 "NSNegateBoolean" は Interface Builder の Inspector/Bindings/ValueTransformer で選択できる文字列と同一のようです。

const の説明は

Const-correctness - Wikipedia, the free encyclopedia
http://en.wikipedia.org/wiki/Const

を参考にしてください。わかりやすく説明されています。


TemperatureConverter の動作を記しておきます。(間違っている可能性もあるので注意してください。)

1. + (void) initialize

クラス ApplicationDelegate が初期化される時に呼び出されるメソッド + (void) initialize で3つの ValueTransformer

Name: centrigradeFromKelvin : CentigradeValueTransformer
Name: fahrenheitFromKelvin : FahrenheitValueTransformer
Name: rankineFromKelvin : RankineValueTransformer

を設定しています。クラスの初期化時に名前を指定して自作のValueTransformerを設定すると良いようです。指定した名前は Interface Builder で利用できます。

2. 伝搬 (簡略化されています。)

TemperatureConverter では ウインドウに表示されている4つ (ケルビン : Kelvin、摂氏: Centigrade、カ氏 : Fahrenhei、ランキン温度 : Rankine) のテキストフィールド (本当はNSFormCell) がすべて LastTemperature にバインドされています。LastTemperature の温度単位はケルビンです。


例えば Centigrade テキストフィールドの値を変更すると

Centigrade テキストフィールドの
ValueTransformer (CentigradeValueTransformer) - (id)reverseTransformedValue:(id)value;
が呼び出され、Kelvin に変換され、LastTemperature に設定される。

LastTemperature が変更されたため、利用している4つ (Centigrade 、Kelvin、Fahrenhei、Rankine) のテキストフィールドに通知される。

Kelvin テキストフィールドは伝わった値を - (void)setObjectValue:(id)object; でテキストフィールドに設定し表示。

Centigrade、Fahrenhei、Rankine テキストフィールドはそれぞれの ValueTransformer (CentigradeValueTransformer、FahrenheitValueTransformer、RankineValueTransformer) の - (id)transformedValue:(id)value; で変換され、その値を - (void)setObjectValue:(id)object; でテキストフィールドに設定する。 - (id)transformedValue:(id)value; の value が LastTemperature。

Cocoa Bindings Programming Topics: Bindings Message Flow
http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/MessageFlow.html#//apple_ref/doc/uid/TP40002149

が参考になります。

*1:Apple Developer Connection [ http://developer.apple.com/ ]