1
votes

I guess I still don't understand this yet. I'm not using ARC on this project.

For a propert, aProperty declared with the retain attribute, I would expect that the assigned object is retained twice in the following statement:

self.aProperty = [UIView alloc] init...];

Once from the alloc, and once by the setter.

So I release the object once immediately, like this:

self.aProperty = [UIView alloc] init...];
[self.aProperty release];

The compiler gives an error message:

Incorrect decrement of reference count of an object that is not owned at this point by the caller.

Is the retain count incremented by the setter, making it two, at that point?

Also, what does "not owned at the point by the caller" mean? This could be a problem that I'm not familiar with.

2

2 Answers

1
votes

Maybe it warns you because the object isn't declared as a simple variable but as owned by somethings else (in this case, self) and wants to prevent you from randomly releasing objects.

Try either this:

UIView *view [UIView alloc] init...];
self.aProperty = view;
[view release];

Or this, what I typically do:

self.aProperty = [[[UIView alloc] init] autorelease];
0
votes

To clarify what is happening.

self.myVar = [[UIView alloc] initWithFrame:frame];

is equivalent to calling

[self setMyVar:[[UIView alloc] initWithFrame:frame]];

When using a @property with retain it's implementation would end up looking something like this (this is just a rough example)

- (void)setMyVar:(UIView *)myVar;
{
    if (_myVar != myVar) {
        [_myVar release];
        _myVar = [myVar retain];
    }
}

So now we can say that

+----------- +1 retain ------------+
|                                  |
[[UIView alloc] initWithFrame:frame]

and

+------ +1 retain ----+
|                     |
_myVar = [myVar retain];

which is +2 for the count. We then would have something like

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

which is -1, which just leaves us with a memory leak as there is stil +1 retain.

The pattern I favour is

UIView *myVar = [[UIView alloc] initWithFrame:frame];
self.myVar = myVar;
[myVar release]; myVar = nil;

so that memory is released as soon as possible and no dangling pointers are left as it is nil'led out