2010-12-07 5 views
4

現代のObjective-Cのランタイムでは、あなたがこのような何かを行うことができますが:@synthesizedインスタンス変数を使用したくないのはいつですか?

@interface MyClass : NSObject { 
} 
@property NSString *stringProperty; 
@end 

@implementation MyClass 
@synthesize stringProperty; 
@end 

これがないだけだろう、私のプロパティのアクセサを合成するだけでなく、インスタンス変数自体現代のランタイムと私の理解です、だから私はこのクラスのメソッド[stringProperty length];の1つで言うことができ、ちょうど私がインスタンス変数を宣言したかのように動作します。

私はこれをすべてのコードで使い始めました。これは、何度も何度も何度も繰り返し書く必要があるからです。そして、私はclang 2.0コンパイラについて聞いたことがありますが、@synthesizeをスキップすることもできます(ただしそれは別の問題です)。しかし、私は疑問に思っていました、これを行うことの欠点のいくつかは何ですか?私のプロパティに本当にインスタンス変数が必要なのはいつですか?

変数をプライベートにして外部にアクセスしたくない場合がありますが(通常は私のプライベートクラス拡張でプロパティを宣言するだけです)、またはプロパティを作成しませんすべて、私はそれのアクセサを必要としない場合)。

私はこれをしたくない場合がありますか?

+0

@joeはい、プロパティを宣言して上記のように合成しても、ivarを明示的に宣言しないと、コンパイラは実際にivarを作成します。だからクラス内で期待しているように 'int len = [self.stringProperty length]'を実行することもできますし、アクセッサメソッドを使わずに 'int len = [stringProperty length]'を行うこともできます。 ivar(コンパイラがsetter + getterと共に私のために合成したもの)。本当に素晴らしいです! – jbrennan

+0

@joe XCode4が現在アプリケーションデリゲートのために生成しているスタブを調べることでこれについて知りました。 –

答えて

4

合成インスタンス変数を使用しないことをお勧めする理由の1つは、現在のバージョンのXcode(3.2.5)でデバッグするのに苦労することです。 GDBでコードを実行しているときにはライブデバッガビューに表示されないようですが、唯一の方法はpo [0xOBJ_ADDRESS propertyName]のようなgdbコンソールです。標準で合成されていないivarほど素晴らしいものではありません。

多分、Xcode 4はこれを修正しましたが、私はそれについて十分な経験がなく(まだNDAの下にあります)。このSO質問に

さらに詳しい情報:Seeing the value of a synthesized property in the Xcode debugger when there is no backing variable

+2

+1これは、下位互換性と共に、(IMO)宣言されたイヴァールを保持する唯一の本当の理由です。デバッグが簡単です。 –

+0

Xcode 4がリリースされた今、これは今のケースですか? – neoneye

+1

@neoneye私が言うことができる限り、はい、Snow LeopardのXcode 4.0.2では、これは残念なことに残念です。 – jbrennan

3

あなたは、例えば、単一のインスタンス変数のための多くの特性を提供することもできます。

  • 長方形にし、極性系
  • に両方の座標にアクセスするための度とラジアン
  • の両方で角度の値にアクセスするために

このような場合、インスタンス変数(すでに存在します)またはアクセサメソッド(変換のために提供する)を合成したくありません。

+1

もちろん、これは実際にインスタンス変数を合成するコンパイラとは関係ありません。私が代わりに 'float angleInDegrees'のためにプロパティを使った' stringProperty'の代わりに言ってみましょう。これは角度で私の角の合成を行い、ラジアンに変換して返す2番目の(readonly)プロパティを追加することができます。私が何かを欠いていない限り、もちろん。 – jbrennan

+0

2番目のプロパティは読み取り専用である必要はありません。ラジアンで表された値を書き込む場合はどうなりますか? '@property float angleInRadians'を追加し、' @合成 'しないで、両方向の変換を行うアクセサメソッドを提供してください。 – mouviciel

1

あなたが直列化する必要のあるクラスで、(誰かがより良い方法を知らない限り)変換を行う必要があるときはいつでも。たとえば、数値を持つクラスがあるとします。整数をシリアル化することはできませんので、クラスにNSNumberとして格納しますが、プロパティは整数型です。

もう1つの例は、CoreDataで作業するときにAppleが推奨するようにコードを作成する場合です。彼らはあなたの管理対象オブジェクトのクラスとしてNSManagedObjectから派生したカスタムクラスを作成し、各属性にプロパティを使用する必要があると言います。次に@synthesizeではなく@dynamicを使用し、iVarは必要ありません。

+0

'[エンコーダーencodeInteger:someIntVar forKey:@" myIntKey "];'あなたのためにやっていないのですか? – jbrennan

+0

それは私が「誰かがより良い方法を知っていなければ」置く理由だろう。私は必要が生じたときにあなたのコードを覚えています。 :-) – Rob

0

もう一つの理由は、変数へのアクセスを指示するためのショートカットを避けるためです。

私は個人的なコーディング規約に従うことを試みる: - オブジェクト変数を:アンダースコアを持つ接頭辞「_xxx」 - プロパティ:アンダースコアなしという名前の「XXX」

この私が意図せずに

ようなものを書くことはありませんことを確認してください
[xxx someMessage]; 

xxx = value; 

または

は、私はいつものgetter/setterメソッドを使用します。

+0

これも私のコーディングスタイルでした。しかし、それは余分に長くて退屈な財産宣言のために作られました。私はコンパイラがivarを合成するときに、ivarNameという名前のプロパティのために_ivarNameという名前でそれを作成する方法があると確信しています。私は調査します。 – jbrennan

+0

私はちょうどそれを試して、はい、可能です。 '@property NSString * myString;' '@synthesize myString = _myString;'はあなたのためにivarを作成し、それは '_myString'と呼ばれ、あなたのプロパティは' myString'と呼ばれます。 – jbrennan

+0

私はこれをGDBで使えるようにしようとは決してしませんでした。それはうまく動作します。この動作に切り替える可能性があります。ところで、XCode 4は、プロパティを宣言するための独自のテクニックでデモされました。いくつかのコードは、書く必要がありません。 –

1

しかし、私は思ってきた

self.xxx = value; 
[self.xxx someMessage]; 

あなたがオブジェクト変数のための怠惰な初期化を使用しているとき、これは特に便利です...、これを行うに欠点のいくつかは何ですか?私のプロパティに本当にインスタンス変数が必要なのはいつですか?

考えられる理由:

  • それはあなたがサブクラスのオーバーライドまたはKVOにつまずくことなく、initdeallocでインスタンス変数を変更することができます。
  • このアプリケーションはMac OS X上で32ビットモードでコンパイルされて実行されます。64ビットをサポートしていないIntel Macもあります。

最初のポイントが本当にどれほど有効かわかりません。問題の周りには他の方法があるかもしれません。古いMacをサポートする必要がある場合、2つめのポイントはゲームオーバーです。

+0

私はこれらの32ビットの古いMacを持っています。私のコードはそれでうまくいくと言えます。(私はMacアプリケーションを書いていませんが、32ビット版のSimulatorでiOSコードを実行すると、それはうまく動作します)。私はおそらくさらに調査する必要があります。 – jbrennan

+0

KVOの例によれば、 'stringProperty = [someString copy];'は、私のinitメソッドから呼び出されたとしても何の問題でしょうか?コンパイラは実際に私のためにivarを作成するので、(私の理解では)KVOを引き起こさないセッターを使わずにアクセスすることができます。しかし、おそらく私はそれについて間違っている。 – jbrennan

+0

OK、古い32ビットMacで、サイコロを試してみました。あなたはMacアプリのために正しいです。同じMacで動作していても、iOSシミュレータで許可されているのは不思議です。以前のMacのランタイムの拡張機能は含まれていなかったのは残念だ。 – jbrennan

関連する問題