42

この質問に対する@mmalc の 回答で、彼は「一般に、dealloc (または init) でアクセサ メソッドを使用しないでください」と述べています。なぜmmalcはこれを言うのですか?

私が考えることができる唯一の本当の理由は、パフォーマンスと @dynamic セッターの未知の副作用を回避することです。

討論?

4

6 に答える 6

29

これは基本的に、バグの可能性を最小限に抑えるためのガイドラインです。

この場合、セッター/ゲッターがオブジェクトの状態について直接的または間接的な仮定を誤って行う可能性があります。これらの仮定は、オブジェクトがセットアップ中または破棄中の場合に問題になる可能性があります。

たとえば、以下のコードでは、オブザーバーは 'Example' が破棄されていることを認識せず、既に解放されている他のプロパティが有効であると想定できます。

(オブジェクトは、それ自体を破壊する前にすべてのオブザーバーを削除する必要があると主張できます。これは良い習慣であり、不注意による問題を防ぐための別のガイドラインです)。

@implementation Example

-(void) setFoo:(Foo*)foo
{
   _foo = foo;
  [_observer onPropertyChange:self object:foo];
}

-(void) dealloc
{
   ...
   self.foo = nil;
}

@end
于 2008-10-10T20:00:48.030 に答える
19

慣用的に一貫したコードを使用することがすべてです。すべてのコードを適切にパターン化すると、init/dealloc でのアクセサーの使用が安全であることを保証する一連の規則があります。

大きな問題は、(mmalc が言ったように) プロパティの既定の状態を設定するコードは、あらゆる種類の厄介な問題につながるため、アクセサーを通過しないことです。問題は、init がプロパティのデフォルト状態をセットアップしなければならない理由がないことです。いくつかの理由から、以下の簡単な例のように、自己初期化するアクセサーに移行してきました。

- (NSMutableDictionary *) myMutableDict {
    if (!myMutableDict) {
        myMutableDict = [[NSMutableDictionary alloc] init];
    }

    return myMutableDict;
}

このスタイルのプロパティ初期化により、実際には必要のない多くの初期化コードを延期できます。上記の場合、init はプロパティの状態を初期化する責任を負わず、init メソッドでアクセサーを使用することは完全に安全です (必要であっても)。

確かに、これはコードに追加の制限を課します。たとえば、スーパークラスのプロパティのカスタム アクセサーを持つサブクラスはスーパークラス アクセサーを呼び出さなければなりませんが、これらの制限は、Cocoa で一般的な他のさまざまな制限と一致しています。

于 2008-10-22T21:10:36.667 に答える
15

あなたはあなた自身の質問に答えました:

  1. パフォーマンスは、それ自体が完全に適切な理由である可能性があります (特にアクセサーがアトミックである場合)。
  2. アクセサーが持つ可能性のある副作用を避ける必要があります。

後者は、クラスがサブクラス化される可能性がある場合に特に問題になります。

しかし、なぜこれが特にObjective-C 2アクセサーで対処されているのかは明らかではありません。宣言されたプロパティを使用する場合でも、アクセサーを自分で記述する場合でも、同じ原則が適用されます。

于 2008-10-11T09:08:32.417 に答える
2

セッターに実行する必要があるロジックがあるか、実装でゲッター/セッターとは異なる名前の ivar が使用されているか、解放する必要があるか、値が nil に設定されている 2 つの ivar が使用されている可能性があります。唯一の確実な方法は、セッターを呼び出すことです。init または dealloc 中に呼び出されたときに望ましくない副作用が発生しないように記述することは、setter の責任です。

「Cocoa Design Patterns」より、Buck, Yacktman, pp 115: 「... 最新の Objective-C ランタイムで合成インスタンス変数を使用する場合、アクセサーを使用する以外に実用的な方法はありません。または ...」

于 2009-10-16T17:52:17.610 に答える
0

割り当て/割り当て解除時にセッターを呼び出さないと、同じ問題が発生する可能性があります。

init/deallocでretain/releaseを直接使用しても何も達成できないと思います。考えられるバグのセットを変更するだけです。

プロパティの割り当て/割り当て解除の順序について考える必要があるたびに。

于 2011-12-09T20:57:47.453 に答える
0

実際、かなり頻繁に出入りするクラス (詳細ビュー コントローラーなど) の場合、init でアクセサーを使用する必要があります。そうしないと、後でアクセスしようとする viewDidUnload の値を解放してしまう可能性があります (CS193P でそれを示しています...)。

于 2011-01-03T21:46:08.900 に答える