5

ヘッダーには次のものがあります。

@property (nonatomic, retain) UIView *overlay;

そして実装では:

@synthesize overlay;

それで:

UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];

tempOverlay上記の変数は不要ではありませんか?私はただすることはできません:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
4

6 に答える 6

11

合成された保持セッターは次のようになります。

- (void)setValue: (id)newValue
{
    if (value != newValue)
    {
        [value release];
        value = newValue;
        [value retain];
    }
}

あなたの場合、2 つの有効な方法があります。

1) 一時変数 alloc/init (=保持) を作成し、プロパティに設定してリリースします。

IView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];

2) 一時変数がなく、ivar に直接設定されます。

overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

更新: 方法 2) を使用する場合は、必要に応じて以前の値を解放することにより、(保持するだけでなく) 残りのメモリ管理を明示的に処理する必要があります。init(たとえば) で1 回だけ実行する場合は、単に a[overlay release];を inに入れることができますdealloc

于 2010-10-13T15:16:31.210 に答える
2

retain属性を使用するretainと、 が新しいオブジェクトで呼び出されるように指定され、以前の値が として送信されますrelease

したがって、2 番目のコード ブロックでは、オブジェクトを解放しなくなり、セッターがそれを保持しているため、オブジェクトの保持カウントは 2 になります。これはあなたが望むものである可能性は低いです。

于 2010-10-13T14:04:15.127 に答える
1

オブジェクトをプロパティに直接割り当てた場合でも、解放する必要があります。

self.overlay = [[[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)] autorelease];
于 2010-10-13T14:20:44.583 に答える
1

プロパティが (保持) で定義されているため、合成されたセッターを使用して (self.overlay 構文を介して) 設定したインスタンスには、自動的に保持メッセージが送信されます。

// You're alloc'ing and init'ing an object instance, which returns an 
// instance with a retainCount of 1.
UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

// The overlay property is defined with (retain), so when you assign the new 
// instance to this property, it'll automatically invoke the synthesized setter, 
// which will send it a retain message. Your instance now has a retain count of 2.
self.overlay = tempOverlay;

// Send a release message, dropping the retain count to 1.
[tempOverlay release];

あなたがするなら:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

オーバーレイの保持カウントが 2 になるため、アプリケーションのある時点でリークが発生する可能性があります。

于 2010-10-13T15:07:48.207 に答える
0

すべての回答ありがとうございます。私はいくつかの矛盾する主張を得たので、私は以下をテストしましたUITableViewController

- (id)initWithStyle:(UITableViewStyle)style {
    if ((self = [super initWithStyle:style])) {
        NSLog(@"count: %d", [overlay retainCount]);
        self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
        NSLog(@"count: %d", [overlay retainCount]);
        [overlay release]; NSLog(@"released once");
        NSLog(@"count: %d", [overlay retainCount]);     
        [overlay release]; NSLog(@"released twice");
        NSLog(@"count: %d", [overlay retainCount]);
    }
    return self;
}

次のコンソール出力が得られました。

  • 時々それはうまくいきました:

    count: 0
    count: 2
    released once
    count: 1
    released twice
    count: 1
    
  • それ以外の場合はクラッシュしました:

    count: 0
    count: 2
    released once
    count: 1
    released twice
    Program received signal:  “EXC_BAD_ACCESS”.
    

使用する方法tempOverlayが正しいことはわかっています。とても面倒に思えますが、どのように機能するのか、いつ呼び出されるのautoreleaseかがわからないので、私はそれを好みます。autorelease1つ確かなことです。overlay保持カウントを2にしたくないので、上記のコードは間違っています。

奇妙なことに、2回リリースすることはできません。クラッシュしない場合でも、保持カウントは減少しません。

とにかく、私はtempOverlay今のところを使用し続けると思います。

于 2010-10-14T00:27:01.827 に答える
-2

はい、新しく作成したオブジェクトをoverlayobject に直接割り当てることができます。必要に応じて、オブジェクトの保持カウントを出力して証明できます。

NSLog(@"count: %d", [overlay retainCount]);
于 2010-10-13T14:10:32.967 に答える