2011-06-19 6 views
1

バインディングを開始するために、私は摂氏温度をケルビンの温度に変換する小さなアプリケーションを作成しています。オブザーバに通知する - バインディングを開始する

私はfloat kelvinfloat centigradeという2つのプロパティにバインドされた2つのNSTextFieldを持っています。もちろん、それぞれのプロパティの値を適切に設定する2つのカスタムセッタがあります。摂氏ため

セッターは次のとおりです。

centigrade = value; 
[self willChangeValueForKey:@"kelvin"]; 
kelvin = value + 273; 
[self didChangeValueForKey:@"kelvin"]; 

私はそうでない場合、値が他のNSTextFieldで更新されていないwillChangeValueForKey:を使用する必要があります。

私の質問は、これを行うよりエレガントな方法はありますか?気温を華氏に変換する別のプロパティとテキストフィールドを追加した場合、そのゲッタにwillChange...didChange...を追加する必要があります。

nibファイルにこれらの2つのプロパティがリンクされていることを伝える方法はありますか?変更するたびに、両方のオブザーバに通知する必要がありますか?

EDIT:

何の価値については、私はcentrigradeのセッターの内側からケルビンのセッターを呼び出して試してみました。しかし、私がケルヴィンのためにセッターでそれを行う場合、それは問題を引き起こしませんか?例えば:/didChangeValueForKey:

centigrade = value; 
[self setKelvin:value]; 

kelvin = value; 
[self setCelsius:value]; 

答えて

2

willChangeValueForKey使用しないでくださいここを、通知は自動的に行われます。通知が表示されない場合は、key-value coding compliant mannerのプロパティを使用していないことを意味します。カスタムセッターはまったく必要ありません。

willChangeValueForKey:/ didChangeValueForKey:これらのプロパティに対して自動kvoを明示的に無効にした場合のみ(これを行う理由がありますが、後でその行を保存する必要があります)。

これを済ませたら、他の問題に取り組むことができます。はい、両方のプロパティのトリガ通知を1つのプロパティに変更させることはできますが、2つ目のプロパティの変更によっても最初のトリガが発生した場合はそれが使用されないことがわかります。

問題はモデルが問題を処理するのに十分なほど洗練されていないことです。あなたはモデルが動作するまで、バインディングをしばらく忘れて、プレゼンテーションを完全に忘れてしまいます。擬似コードでは、浮動小数点の詳細を無視して、あなたは、少なくともこの作業のようなものを取得する必要があります: - あなたはKVOのcomplienceのガイドに従ってください(とそれを使用する際に理解していないときに仮定し

model.celcius = 100.0; 
assert(model.kelvin == 373.0) 

model.kelvin = 0.0; 
assert(model.celcius == -273.0) 

を - すなわちあなたは通知をトリガーするタイミングを制御しています)、あなたはテキストフィールドのバインディングをフックできるようになり、すべてがうまくいくでしょう。この作品を作るための鍵は、temperatureKelvinの値を更新するtemperatureFahrenheitとtemperatureCelciusが変更された通知を送信することを確認することです

@property (assign) float *temperatureKelvin; // only one instance variable needed 

- (float)temperatureFahrenheit { 
    return tempeatureKelvin * ...;    // whatever formula is 
} 

- (float)temperatureCelcius { 
    return tempeatureKelvin * ...;    // whatever formula is 
} 

- (void)setTemperatureFahrenheit:(float)val { 
    self.temperatureKelvin = val * ...;   // whatever formula is 
} 

- (void)setTemperatureCelcius:(float)val { { 
    self.temperatureKelvin = val * ...;   // whatever formula is 
} 

- :

これは次のようになります。これを従属性のある事前属性として登録することでこれを行います。

+ (NSSet *)keyPathsForValuesAffectingTemperatureFahrenheit { 
    return [NSSet setWithObject:@"tempeatureKelvin"]; 
} 

+ (NSSet *)keyPathsForValuesAffectingTemperatureCelcius { 
    return [NSSet setWithObject:@"tempeatureKelvin"]; 
} 
+0

私は完全にオフトラックだったと感じました。私は私のモデルKVOに準拠させる必要があると推測しているだけで、2つのフロートプロパティを持つことはそれをカットするつもりはありませんか?さらに、私はカスタムセッターを一切必要としていないと主張しています。ケルビンを摂氏に変換したり、逆にケルビンを変換するコードが必要なのですか? – saad

+0

私は+ keyPathsForValuesAffectingValueForKeyもオーバーロードしていますが、それもうまくいくようです。しかし、私はまだあなたがモデルについて言ったことに熱心です。 FWIW、私は基本的なモデルを持っていますが、カスタムアクセサを削除すると明らかに温度は変わりませんが値は変更されますが、合成されたセッター/ゲッタはまだ呼び出されており、値は更新されます。私は同じプロパティに2つのテキストフィールドを接続し、一方を変更してもう一方を更新することで確認しました。 – saad

+0

もう少し説明を追加しました。モデルについてのポイントは、あなたが複雑なモデルを必要としているということではありません。あなたのビューとは独立して、好ましくは単体テストでそれを開発することが良いということです。 – hooleyhoop

関連する問題