次のコードに問題がありますか?Objective Cのdeallocでのsetterの使用?
- (void) dealloc {
self.foo = nil;
}
代わりの
- (void) dealloc {
[_foo release];
_foo = nil;
}
次のコードに問題がありますか?Objective Cのdeallocでのsetterの使用?
- (void) dealloc {
self.foo = nil;
}
代わりの
- (void) dealloc {
[_foo release];
_foo = nil;
}
:サブクラスはセッターをオーバーライドしている場合
は、リリースには、実際には起こらないかもしれません。
setterを使用すると、KVO通知がトリガされ、オブザーバは、技術的に存在しないオブジェクトから通知を受け取ります。
一方、ARCを使用する場合は、その必要はありません。
問題ありませんあなたはretain
かcopy
属性が、あなたは[_foo release];
を行うべきではありませんassign
を使用してそれをしなかった場合は、これを見つけるかもしれないとあなたのfoo
プロパティを宣言した場合便利な読み: Objective-C Memory Management for the Lazy
それが推奨されないのは、問題を引き起こす可能性があるからです。セッターまたはゲッターに副作用がある可能性があります。
メモリリークのこの例を考えてみましょう。
- (void)dealloc;
{
self.iWillLeak = nil;
self.iCauseTheLeak = nil;
[super dealloc];
}
- (void)setICauseTheLeak:(NSArray *)iCauseTheLeak;
{
if (_iCauseTheLeak != iCauseTheLeak) {
[_iCauseTheLeak release];
_iCauseTheLeak = [iCauseTheLeak retain];
}
self.iWillLeak = [NSArray array]; // This was already cleared in dealloc
}
これは単純なケースであり、より多くの損害を与える可能性があります。
ここでの主なテイクアウトは、2つの機能が同じではないことです。旧を行うにはない二つの理由があります
私は2つの例を記述します:
1 /を直接
- (void)dealloc {
[foo_ release];
[super dealloc];
}
- (void)setFoo:(Foo*)foo {
if (foo == foo_) {
return;
}
[foo_ removeObserver:self];
[foo_ release];
foo_ = [foo retain];
[foo_ addObserver:self];
}
のリリースを使用してfoo_
からのオブザーバーは、おそらく誤りである、削除されません。セッター
- (void)dealloc {
self.observer = nil;
self.foo = nil;
[super dealloc];
}
- (void)setFoo:(Foo*)foo {
if (foo == foo_) {
return;
}
[foo_ removeObserver:self.observer];
[foo_ release];
foo_ = [foo retain];
[foo_ addObserver:self.observer];
}
を使用して
2 /あなたが見ることができるように、別のエラーがここに表示されます。我々は、(self.observer
)のどこかでnil
がおそらく期待されていないところを使用しています。
一般に、この2つのケースのどちらも、あなたのバグを捕まえるのに役立ちません。どのような場合でも、さまざまな種類のバグが発生する可能性があります。
私のお勧めは、一貫性を維持するために設定者を使用することですが、それは意見の問題です。 とにかく、独自のセッターを書く場合は、プロパティを正しい順序で初期化しているかどうかを確認してください。また、セッターはサブクラスでオーバーライドできます。
アップルは、initとのdeallocで直接保持/解放を使用することをお勧めしますが、独自のコードでは、それらは(解放とき例えばUITableView
はnil
パラメータでsetDelegate
を呼び出し)セッターを使用します。
1つの注意点... ARCを使用していない場合は、[[super dealloc]]を呼び出す必要があります。そうであれば、 'release'を呼び出すべきではありません。 –