2011-02-03 10 views
5

SomeObjectが@property(非原子的、保持)で作成されたクラスプロパティである場合、someObject = someOtherObject;self.someObject = someOtherObject;の設定の違いを誰でも説明できますかSomeType someObject;私は自己のないプロパティを使用するとき、私は時々EXC_BADアクセスを取得し、それはかなりランダムなようで気づいた自己と不動産にアクセスする場合はいつですか?

@interface SomeClass : NSObject { 
    SomeType* someObject; 
} 

@property (nonatomic, retain) SomeType* someObject; 

@end 

は、私のようなものを持って明確にします。私が自己を使うとき、私のプログラムはそれがすべきであるように行動します。私は自己をスキップするとコンパイラのエラーや警告が出ないので、何とか正しい構文になっていると思いますか?

+0

[selfキーワードを使用する必要がある場合]の可能な複製(http://stackoverflow.com/questions/4080523/when-should-i-use-the-self-keyword)質問する前に検索しますか? – zoul

答えて

2

プロパティは、データにアクセスするのに便利な方法です。したがって、プロパティ@property(nonatomic、retain)を宣言しているときSomeType * someObject;これは、アクセス時に2つの方法が合成されることを意味する:

ゲッター:

-(SomeType*) someObject { 
    return someObject; 
} 

セッター

-(void) setSomeObject:(SomeType*) obj { 
    [someObject release]; 
    someObject = [obj retain]; 
} 

だから特性とアイバーズの間の主な違いは、プロパティが動的セッター/ゲッターを作成することですメソッドをオーバーライドすることができます。しかしsomeObject = new_valを書いているときは、参照をメモリ位置にコピーするだけです。 1つのアセンブリ命令を除き、そこでは追加作業は行われません。

言及すべきもう1つのことがあります:原子と非原子。 アトミックでは、合成されたsetter/getterは、他のスレッドのセッターアクティビティに関係なく、ゲッターから常に値全体が返され、セッターによってセットされることを保証します。つまり、スレッドBがセッターを呼び出している間にスレッドAがゲッターの途中にある場合、実際に実行可能な値、つまりおそらくオートレリースされたオブジェクトがAの呼び出し元に返されます。

非原子的で、そのような保証は行われません。したがって、非原子的は原子よりかなり速い。

編集:異なるスレッドからアクセスされる変数や、いくつかの追加作業が必要な場合(例えば、保持、いくつかのフラグを立てるなど)、あなたの選択はプロパティです。しかし、時には非常に頻繁にアクセスされる変数があり、プロパティを介したアクセスは大きなオーバーヘッドにつながることがあります。これは、プロセッサがメソッドを合成し呼び出すためにはるかに多くの操作を実行する必要があるためです。

4

self.someObject = someOtherObjectは、このプロパティを利用しています。プロパティは、セッターとゲッターを生成します。あなたのケースでは、プロパティにretain属性を指定しました。つまり、このプロパティを介して設定されたオブジェクトは、自動的にretainメッセージを受信し、保持カウントが1増加します。さらに、メンバ変数の古い値はreleaseメッセージ保持カウントが減少します。

オブジェクトの保持カウントが0になると、オブジェクトの割り当てが解除されます。割り当てが解除されたオブジェクトにアクセスしようとすると、EXC_BAD_ACCESSオプションが表示されます(あまりにも頻繁に解放しようとするなど)。あなたのケースでは

:あなたがセッターを使用しない場合

SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1 
self.someObject = soo; //soo's retain count is now 2 
[soo release]; //soo's retain count is 1 again, as self still uses it. 
[self doSomethingWithSoo]; 

しかし、あなたはsooを解放してはいけません。

SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1 
someObject = soo; //soo's retain count is still 1 
[soo release]; //soo's retain count is 0, it will be deallocated 
[self doSomethingWithSoo]; //will fail with an EXC_BAD_ACCESS exception, as soo does not exist anymore. 
0

2つの違いは次のとおりです。

1)あなたが使用していない時に "自己を。"結果をメンバー変数に直接代入します。

2)「自己」を使用している場合。そのプロパティでsetterメソッドを呼び出しています。これは[self setMyObject:...]と同じです。

self.myobjectの場合は保持を保持し、その他の場合は(自己なしで)allocを使用していない場合は、自動解放されたオブジェクトとして扱われます。

ほとんどの場合、オブジェクトの初期化中を除き、「自己」を使用することができます。ところで

、あなたはまた、それは、メモリ管理についてのすべてだカウンター

1

を維持向上させるためにself.someObject = [someOtherObject retain]を使用することができます。

クラスプロパティsomeObjectは、.h/.mファイルに@property/@synthsizeの注釈を持つアクセサを生成しています。

someObjectでプロパティにアクセスしているときは、そのプロパティに直接アクセスします。 self.someObjectにアクセスする際には、あなたのアクセサリーを[self someObject]と呼んでいます。あなたのためにメモリ管理が面倒です。

クラスプロパティを割り当てる必要がある場合は、セッターを使用しているため、離して保持する必要がないため、self.someObject = someOtherObject;を行うのがよりクリーンです。あなたのセッターは@property (nonatomic, retain)で生成されるので、あなたのために保持するように注意します。

関連する問題