それはイヤーズを扱う正しい方法ですか?

私はgetterとsetterに関する多くの話題を読んだ。私は彼らが何で、なぜ有用であるかを知っています。さまざまなソースの主張は、イヤーズをリリースするさまざまな方法です。ここで私の混乱が始まります

@interface CoolClass : NSObject
{
  NSString *name;
}

@property (nonatomic, copy) NSString *name;
@end

@implementation CoolClass
@synthesize name = _name;

-(id)init
{
  if(super = [self super])
  {
     self.name = @"Jo";
  }
  return self;
}

-(void)dealloc
{
  [self.name release], self.name = nil;
}
@end

それがイバールを解放する正しい方法ですか?

3
@Profo回答を投稿してください: self = [super init] にする必要があります super = [self super]
追加された 著者 justin,
コンパイラの警告を避けるために、if((super = [super init]))もdouble(()で記述する必要があります。
追加された 著者 Nick Lockwood,

3 答え

ほとんどの場合、アクセサーを使用したいが、負の副作用があります。ここでそれはどのように行われます:

- (id)init
{
  if((self = [super init])) {
    //self.name = @"Jo"; << don't use accessors in initializer

     _name = [@"Jo" copy]; << good
  }
  return self;
}
// added for another variation:
- (id)initWithName:(NSString *)inName
{
  if((self = [super init])) {
     _name = [inName copy];
  }
  return self;
}

- (void)dealloc
{
   //don't use accessors in dealloc
   //don't release the result of a getter (release the result of the retained or copied result)
   //[self.name release], self.name = nil;  

   //instead:
    [_name release], _name = nil;
    [super dealloc]; << compiler should have warned you about this one
}

注意: init の場合、文字列リテラルは不滅です。私の好みは、不必要ではあるが、明確にするために不滅をコピーすることです。

2
追加された
@meccan私はリンゴのために話すことができません。しかし、サンプルのアプローチはバグの原因となる可能性があります。実装はいつでも変更でき、副作用がなくても保証はありません。実装のオーバーライドと実装にも依存します。プログラムが一定量の複雑さに達すると、定義された順序と振る舞いの境界を観察することが最良です(IMO)。多くの人が私が過度に慎重だと思う - プログラムの成功率は98%で十分ではない(IMO)。頻繁に例外を発生させるプログラムでは、多くのメンテナンス(YMMV)が必要です。
追加された 著者 justin,
@メッカンっ。クラスメソッド: +(MyLabel *)labelWithText:または +(MyLabel *)newLabelWithText:
追加された 著者 justin,
自己のプロパティのための@meccan、私はちょうど指定されたイニシャライザの1つを使用して、initで私のivarsを設定し、残りの部分をクライアントに残します。私が実際にこの機能を本当に必要とする特別な場合には、これを達成するために便利なコンストラクタを使用します。
追加された 著者 justin,
@meccan私はそれを主張している人々と協力してきました。それだけでなく、 "開発中の問題に気付いた場合、IBOutletsをゼロにするために dealloc viewDidUnload を呼び出す..."
追加された 著者 justin,
@meccanここに私が間違っている可能性のある事柄のいくつかを示す記事を書いた: stackoverflow.com/questions/5932677/…
追加された 著者 justin,
@Profo NSString リテラル(例: @ "こんにちは!" )はあなたのプログラムの生涯にわたって生きていて、決してdeallocされません。
追加された 著者 justin,
@meccan私もかなり自分自身を使っていますが、私は今9年間objcを書いていますので、私はそれほど頻繁に私に悪影響を及ぼさないほどの間違いを犯しました。あなたはこの記事が好きかもしれません: 追加された 著者 justin,
@profoでは、それがリテラルから何かに変更された場合、リークを導入したくないので、それを通常通り保持/コピー/解放するのは良い習慣です。
追加された 著者 Nick Lockwood,
@ Justinあなたはオートレリースされたオブジェクトを返すクラスメソッドを意味しますか?例えば - (MyLabel *)labelWithText:(NSString *)text {MyLabel * l = [[MyLabel alloc] init]; l.text =テキスト; return [l autorelease];} ??
追加された 著者 CarlJ,
私はいつもiVar =を使用してコメントと良い外観のためのthx)
追加された 著者 CarlJ,
そしてなぜdocusの動作を使っているのですか?これは間違った方法ですか? を "> developer.apple.com/library/mac/documentation/Cocoa/Conceptu&zwnj noreferrer nofollowを
追加された 著者 CarlJ,
最後に@Justin質問:あなたがたとえばから拡張する場合は、イニシャライザでプロパティを設定する最良の方法は何ですか?あなたがイニシャライザのiVarsにアクセスすることができないので、UILabel ...
追加された 著者 CarlJ,
イニシャライザでアクセサーを使用しない理由は何ですか?
追加された 著者 CarlJ,
@ジャスティン私はちょうどsomのobjC/Cocoa Developer BookをApressや著者から頻繁にアクセスして、イニシャライザのivar ...でクッキー=)
追加された 著者 CarlJ,
「不滅」とはどういう意味ですか?
追加された 著者 Profo,

ここに私が助言するものがあります:

@interface CoolClass : NSObject
@property (nonatomic, copy) NSString *name;
@end

@implementation CoolClass
@synthesize name = _name;

-(id)init
{
  if(super = [self super])
  {
     self.name = @"Jo";
  }
  return self;
}

-(void)dealloc
{
  [_name release];
  [super dealloc];
}

@end

ノート:

  1. ヘッダー内の{...}の内部にivarsを明示的に宣言する必要はありません。あなたの財産を合成するときに自動的に作成されます。明示的なイヴァールは、iOS 3以降はもはや必要ではない従来のコンセプトです。

  2. deallocでself.nameを使用しないでください。これはgetterメソッドを呼び出すため、単にivarをフェッチする以外の追加作業が必要な場合があります。通常、getterメソッドを使うのは良い方法ですが、deallocでは直接ivarを解放する必要があります。

  3. ivarsを解放してからnilに設定することをお勧めしますが、deallocの後でコードが実行されないため、deallocでこれをもう一度実行する必要はありません。 >

  4. 通常は(deallocの外で)ivarをリリースしたい場合は、次のようにsetterを使ってnilに設定する必要があります:self.name = nil;自動的にそれをリリースし、それをnilに設定します。これは[_name release]、_name = nil;と同等です。

1
追加された
ここでは問題ではない@NickLockwood - 私は常に @private ivarsを使い、パラレルイニシャライザを決して呼び出しません。
追加された 著者 justin,
@NickLockwoodは、実際のオブジェクトグラフがどのように構築されるかではなく、弱い参照などのコーナーケースがあります。
追加された 著者 justin,
@Nickについて#3: dealloc でのダングリング参照。それはまれですが、それは起こります。
追加された 著者 justin,
サブクラスのdeallocが "do not do any work"ルールに違反している場合のみ。たとえば、他の象牙を参照するセッター/ゲッターメソッドを呼び出す場合です。あなたがdeallocに置く唯一の事柄がリリース文であり、通知やKVOオブザーバーから登録を解除するなら(あなたがそうしているように)、あなたは大丈夫でしょう。
追加された 著者 Nick Lockwood,
けっこうだ。それは私が遭遇した問題ではないが、理論的にどのように起こるかを見ることができる。同じ行に沿って、initは同じivarを設定する別の継承initを呼び出すため、initで直接ivarsを設定すべきではありません。
追加された 著者 Nick Lockwood,
その上の@Justin通知self.name = @ "Jo"はincorectです、あなたはそれを確認できますか?
追加された 著者 Profo,
@interface CoolClass : NSObject
{
  NSString *name;
}

ここでインスタンス変数 'name'を宣言しました。現在、ヘッダーファイルにivarsを宣言する必要はありません。プロパティを使ってコンパイラにivarを合成させてください。

@property (nonatomic, copy) NSString *name;

ここでは、オブジェクトのコピーを代入に使用し、前の値に解放メッセージを送信することを指定するプロパティ宣言があります。

実装では、あなたのプロパティを合成したい:

@synthesize name = _name;

このコードは、 'name'というプロパティのgetterとsetterを生成し、 '_name'という名前のインスタンス変数を使用して値を格納するようにコンパイラに指示します。だからあなたは今や2つのイヴァールを持っています - 「名前」と「_name」。

initメソッドは以下のようになります:

-(id)init
{
  if(self = [super init])
  {
     name = @"This is ivar declared between {}";
     _name = @"synthesized ivar";

  }
  return self;
}

そしてdealloc:

-(void)dealloc
{
  [name release];
  [_name release];
  [super dealloc];
}
1
追加された
@NickLockwoodええ、私はOPでいくつかのものをスキミングしています - 眠くなる=)
追加された 著者 justin,
@NickLockwood naganはOPが2つのイヴァールを宣言したことを示しています。
追加された 著者 justin,
なぜあなたはあなたのdeallocに[name release]を2回置いたのですか?
追加された 著者 Nick Lockwood,
ああ、良い点 - それは私にスキムリーディングを教えるでしょう;-)
追加された 著者 Nick Lockwood,