12

例:

- (NSString*) title {
    return [[title retain] autorelease];
}

セッターは実際にそれをすでに保持していましたよね?実際、誰もセッターをバイパスするべきではありません...では、なぜゲッターはオブジェクトを返すだけではないのでしょうか。実際にはすでに保持されています。それとも、その間に別のオブジェクトがセッターに渡される場合に備えて、これが必要になるでしょうか?

4

4 に答える 4

12

こちらからhttp://www.macosxguru.net/article.php?story=20030713184140267

- (id)getMyInstance
    {
        return myInstanceVar ;
    }

また

- (id)getMyInstance
{
    return [[myInstanceVar retain] autorelease] ;
}

違いは何ですか?2 つ目は、呼び出し元がコンテナー オブジェクトのインスタンス変数を取得し、コンテナーを破棄し、現在の自動解放されたプールの次のリリースまで、間接的に生成されたインスタンス変数の解放によって損なわれることなく、インスタンス変数を使用し続けることを可能にします。そのコンテナのリリースによって:

aLocalVar = [aContainer getAnInstanceVar] ;
[aContainer release];
doSomething(aLocalVar);

「get」が最初の形式で実装されている場合は、次のように記述する必要があります。

aLocalVar = [[aContainer getAnInstanceVar] retain];
[aContainer release];
doSomething(aLocalVar);
[aLovalVar release];

最初の形式は、コード実行速度の点で少し効率的です。ただし、他の人が使用するフレームワークを作成している場合は、2 番目のバージョンをお勧めする必要があります。これにより、フレームワークを使用する人々の生活が少し楽になります。自分が何をしているのかについてあまり考える必要がありません。 ) 最初のスタイル バージョンを選択した場合は、それをドキュメントに明確に記載してください... どの方法を選択する場合でも、バージョン 1 からバージョン 2 への変更はクライアント コードの節約になることを覚えておいてください。バージョン 2 からバージョン 1 に戻ると、既存のクライアントコード…</p>

于 2009-04-29T11:30:03.527 に答える
7

誰かがコンテナを解放した場合だけではありません。その場合、オブジェクト自体を保持する必要があることがより明白だからです。次のコードを検討してください。

NSString* newValue = @"new";
NSString* oldValue = [foo someStringValue];
[foo setSomeStringValue:newValue];
// Go on to do something with oldValue

これは合理的に見えますが、setter も getter も autorelease を使用しない場合、oldValue の割り当てが解除されているため、"Go on to do something" の部分がクラッシュする可能性があります (他の誰もそれを保持していないと仮定します)。通常は、 Apple のアクセサ メソッドの例にあるテクニック 1 またはテクニック 2 を使用したいので、上記のようなコードはほとんどの人が期待するように機能します。

于 2009-04-29T20:32:49.247 に答える
4

Compare this code

  return [[title retain] release]; // releases immediately

with this

  return [[title retain] autorelease]; // releases at end of current run loop (or if autorelease pool is drained earlier)

2 番目のものは、クライアントが操作する非割り当てオブジェクトを持つことを保証します。

これは、次のような状況で役立ちます (クライアント コード)。

 NSString *thing = [obj title];
 [obj setTitle:nil]; // here you could hit retainCount 0!
 NSLog(@"Length %d", [thing length]); // here thing might be dealloced already!

メソッド内の保持 (および のautorelease代わりに を使用release)titleにより、このコードが爆発するのを防ぎます。release自動解放されたオブジェクトは、現在のコール スタックの実行が完了するまで (現在の実行ループが終了するまで) 、そのメソッドが呼び出されません。これにより、コール スタック内のすべてのクライアントコードが、解放されることを心配することなく、このオブジェクトを使用できるようになります。

覚えておくべき重要なこと:これは Java、Ruby、または PHP ではありません。yer [sic] 変数にオブジェクトへの参照があるからといって、それがあなたの下から解放されないという保証はありません。保持する必要がありますが、解放することを忘れないでください。Autorelease を使用すると、これを回避できます。多くの反復を伴うプロパティまたはループを扱っていない限り、常にautorelease を使用する必要があります (問題が発生しない限り、おそらくそうではないでしょう)。

于 2011-05-18T04:34:29.083 に答える
0

私はこれまでこのパターンを見たことがありませんが、それは私にはかなり無意味に思えます。クライアントコードが親オブジェクトで「release」を呼び出した場合、戻り値を安全に保つことが目的だと思います。それは実際には何も害はありませんが、うまく設計されたライブラリで状況が頻繁に発生することはないと思います。


ああ、わかりました。リンクされたドキュメントsmorganから、これは現在Appleが人々に使用することを推奨している方法の1つであるようです。私はまだ古い学校のバージョンを好むと思います:

- (NSString *) value
{
    return myValue;
}

- (void) setValue: (NSString *) newValue
{
    if (newValue != myValue)
    {
       [myValue autorelease]; // actually, I nearly always use 'release' here
       myValue = [newValue retain];
    }
}
于 2009-04-29T19:13:59.187 に答える