1

このようなプロパティが1つある場合、最初のモードと2番目のモードのプロパティの値を割り当てることの違いは何ですか?

@interface Prueba : NSObject{
    CustomeClass *_cclass;
}
@property(nonatomic, retain)CustomeClass *cclass;

@end

@implementation Prueba

@synthesize cclass = _cclass

- (void)config{
    // 1 This
    self.cclass = [[CustomeClass alloc] init];

    // 2 This or
    CustomeClass *cc = [[CustomeClass alloc] init];
    self.cclass = cc;
    [cc release];
}

@end

:/

4

2 に答える 2

0

最初の例では、保持カウントが 2 のオブジェクトが返されます (間違っています)。2 番目の例では、保持カウントが 1 のオブジェクトが返されます (右)。2 番目の方法は、非 ARC プロジェクトで推奨されます。または、自分でivarを設定することもできます(セッターを使用していないため、これは好きではありません):

_cclass = [[CustomeClass alloc] init];

または、例のようにセッターを使用しますが、自動解放を行います(必要がない限り、リリースを延期すべきではないため、私は好きではありません):

self.cclass = [[[CustomeClass alloc] init] autorelease];

非 ARC プロジェクトでは、元の 2 番目の例が最適です (ポインターを使用し、プロパティのセッターを使用してからポインターを解放します)。KVO では、セッターを使用する習慣を身に付けたいからです。

CustomeClass *cc = [[CustomeClass alloc] init];
self.cclass = cc;
[cc release];
于 2012-05-13T06:47:31.040 に答える
0

2 番目のメソッドで追加のポインターを作成することを除いて、結果に違いはありません。どちらのバージョンでself.cclassも、オブジェクトを問題なく保持できます。

問題は、2 番目のモードでのみオブジェクトを解放すると、最初のモードでメモリ リークが発生することです。retainCountオブジェクトを割り当てると +1 になるため、setter を介して +1 オブジェクトを割り当てます。これは、実際にretainCountもう一度ぶつかることを意味します。オブジェクトをプロパティに割り当てた後にオブジェクトを解放しない場合、そこから解放されると、は 1 だけ減少します。したがって、 +1retainCountのオブジェクトがメモリ内を浮遊し、永久に失われます。retainCount

しかし、あなたはすでにより良いバージョンについて尋ねているので、遅延インスタンス化を紹介したいと思います。できることは、問題のプロパティの getter メソッドを上書きし、まだ割り当てられているかどうかを確認することです。そうでない場合は、getter メソッド内で割り当ててから返します。次のようになります。

- (CustomeClass*) cclass
{
  if(!_cclass)
  {
    _cclass = [[CustomeClass alloc] init];
  }
  return _cclass;
}

このメソッドでは、+1 保持オブジェクトを内部変数に割り当てます。したがって、setter をバイパスし、retainCount. また、オブジェクトは本当に必要な場合にのみインスタンス化されるため、メモリに優しいです。プロパティを nil または新しいオブジェクトに設定すると、古いオブジェクトは適切に割り当て解除されます。

編集:

Robert Ryan のコメントに応えて、以下を追加します。

これにより KVO が壊れたり、プロパティに割り当てられた資格が妨げられたりすることはありません。プロパティがassignまたはとしてマークされている場合weak、遅延インスタンス化はあまり意味がありません。としてマークされている場合、retainまたはstrongオブジェクトをインスタンス化するこの方法は完全に問題ありません。特に、構成メソッド内でとにかく割り当てるプロパティである場合はそうです。

KVO について: getter 内で割り当てられた値は初期値/デフォルト値と見なすことができるため、KVO は引き続き機能します。セッターを使用してプロパティに何か他のものを割り当てると、トリガーされます。デフォルト値が原因で KVO がトリガーされるのは望ましくありません。

于 2012-05-13T06:35:46.807 に答える