Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is retain setter implemented with @synthesize?

I have the following in the header:

@property (nonatomic, retain) UIView *overlay;

And in the implementation:

@synthesize overlay;

Then:

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

Isn't the tempOverlay variable above unnecessary? Can't I just do:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
like image 504
ma11hew28 Avatar asked Oct 13 '10 13:10

ma11hew28


4 Answers

A synthesized retained setter looks like :

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

In your case, you have two valid methods :

1) Create a temp var, alloc/init (= retained), set to property, release.

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

2) No temp var, set directly to ivar.

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

UPDATE: If you use method 2), you have to explicitly handle the rest of memory management (not only retaining), by releasing any previous value it might have before if needed. If done only once in init (for instance), you can just put a [overlay release]; in dealloc.

like image 124
jv42 Avatar answered Nov 15 '22 00:11

jv42


Using the retain attribute specifies that retain should be invoked on the new object, and the previous value is sent a release.

So in your second code block, the retain count of the object would become 2, since you no longer release it, and the setter is retaining it. This is unlikely to be what you want.

like image 26
Nick Moore Avatar answered Nov 14 '22 23:11

Nick Moore


If you assign the object directly to the property, you still must release it:

self.overlay = [[[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)] autorelease];
like image 31
Leg10n Avatar answered Nov 15 '22 00:11

Leg10n


As your property is defined with (retain) any instance you set using the synthesized setter (via the self.overlay syntax) will automatically be sent a retain message:

// 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];

If you were to do:

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

Your overlay would have a retain count of two, which will likely lead to a leak at some point in your application.

like image 39
dannywartnaby Avatar answered Nov 15 '22 00:11

dannywartnaby