私はあなたがしなければあなたが最も確かにメモリリーク持って、次のことを知っている:これは客観的なメモリリークですか?
id foo = [[NSObject alloc] init];
foo = nil;
をしかし、あなたはself.foo、保持してプロパティを何を使っている場合は?あなたのコードは、次のようになります。
アクセサーがメモリを解放してからnilに設定するとメモリリークが発生しますか?
私はあなたがしなければあなたが最も確かにメモリリーク持って、次のことを知っている:これは客観的なメモリリークですか?
id foo = [[NSObject alloc] init];
foo = nil;
をしかし、あなたはself.foo、保持してプロパティを何を使っている場合は?あなたのコードは、次のようになります。
アクセサーがメモリを解放してからnilに設定するとメモリリークが発生しますか?
self.foo = nil
にはメモリリークがここにありません
[nil retain]
[foo release]
foo = nil
につながるでしょう。
いいえ、2番目の例はメモリリークではありません。実際には、それは私のdealloc
メソッドのretain
プロパティを処理する方法です。それはちょうど多くのクリーナーです。
あなたは注意する必要があり唯一のことは、あなたがオブジェクトをダブル保持し、メモリリークになってしまいます
self.foo = [[NSObject alloc] init];
か、他に書くことがわからない行っています。
あなたは本質的にセッターを使用し、無料でメモリ管理を取得しているとは思わないと思います。self.foo = nil
プロパティは、あなたのコードを代入のように見せますが、現実にはObj-C 2.0より前に書いた従来のアクセサメソッドと同じです。プロパティを使うとObj-Cは宣言で指定したキーワードを使用する代わりに(@synthesizeを使用し、独自のアクセサメソッドを作成しないと仮定して)、舞台裏でアクセサーメソッドを生成しています。
いいえ、メモリリークはありません。あなたの第二の例のコードは
foo = [[NSObject alloc] init];
[nil retain];
[foo release];
foo = nil;
と論理的に等価である@synthesizedセッターが
- (void)setFoo:(id)newFoo {
[newFoo retain];
[foo release];
foo = newFoo;
}
にlogicall同等であるので、それは直接foo
を設定すると、おそらくあなたが外でやりたいものではないことは注目に値しますinitメソッド。 foo
に値を直接割り当てると、willChangeValueForKey:/didChangeValueForKey:
ペアで割り当てをラップする必要がありますと のすべての変更を期待して、setFoo:
メソッドをオーバーライドすると、サブクラスの動作が破損します。セッターを通過する。
setFoo:
メソッドまたはサブクラスのオーバーライドsetFoo:
メソッドが副作用を持つか、インスタンスが完全に初期化されていることが原因で、initメソッドで直接foo
に割り当てられます。
同様に、同じ理由で-dealloc
メソッドでself.foo = nil;
ではなく[foo release]
を使用します。
これまでの回答すべては、2番目の例の1行目の "foo
"がfoo
プロパティの背後にあるインスタンス変数であると仮定しています。これがデフォルト動作です。
最初の行に割り当てられているfoo
がローカル変数である場合、foo
プロパティは無関係であり、メソッドの後半でオブジェクトを解放しない限り、オブジェクトはリークします。
foo
がインスタンス変数であるが、foo
プロパティが実際には異なるインスタンス変数またはインスタンス変数によってサポートされていない場合は、(a)メンテナンスが難しいコードを記述しています。(b)漏れである。
最後に、以前の回答をエコー:foo
はfoo
プロパティをバックアップするインスタンス変数がある場合、これはあなたが2行目に呼び出すsetFoo:
メソッドは、オブジェクトを解放しますので、あなたはfoo
に入れている、リークではありません最初の行のインスタンス変数。
他に誰も気づいていないようです:は、リークがかもしれません。
私はfoo
はIVARとretain
プロパティの両方であることを前提としています:自体に漏れない、ということ
-(void)bar {
foo = [[NSObject alloc] init];
self.foo = nil;
}
:
@interface Foo : NSObject {
NSObject * foo;
}
@property (nonatomic, retain) NSObject * foo;
@end
はのは、あなたのコードは次のようになりますしましょうが提供された場合、foo
はゼロから始まり、で始まりました。それはあなたがそれらの一方のみを呼び出すことを想定しているためfoo = [[Foo alloc] init]
よう
-(void)baz {
self.foo = [[NSObject new] autorelease];
}
-(void)fubar {
[self baz];
[self bar];
}
スタッフは、init
-methodsで、一般的に安全なのでfoo
がされている:あなたは、いくつかのより多くのコードを追加しましょう - それはそれは漏れないという意味ではありません。最初はnil
であることが保証されています。どこにいても、もう少し注意する必要があります。
// Use assertions so it crashes debug builds if it's already set
assert(!foo);
foo = [[NSObject alloc] init];
self.foo = nil;
// Or release explicitly.
[foo release];
foo = [[NSObject alloc] init];
self.foo = nil;
// Or just use the setter, which will do the "right thing".
// This is particularly relevant for "copy" or "assign" accessors.
self.foo = [[[NSObject alloc] init] autorelease];
self.foo = nil;
deallocのプロパティを使用することは、別のivar(すでにリリースされているかもしれない)を変更するためにアクセサーメソッドが変更された場合には、通常避けてください。私はちょうどリリースを代わりに使用します。 –
@Alex:優秀な警告の場合は+1、deallocメソッドではself.foo = nilを使用することを提案する場合は-1です! –
@eJames self.foo = nilは、元々deallocメソッドでそれを行うことを推奨していた方法であり、サンプルコードのどこにでもあります。 –