3

I've been teaching myself Objective C recently, and have noticed the following pattern used a lot in tutorials and sample code (including samples from the Apple site).

UIView *myUiView = [[UIView alloc] init];
self.uiView = myUiView;
[myUiView release];

I was just wondering though, it seems a bit of a waste to create a new variable, just to set a property. I've also seen the following pattern used too, but from what I understand its considered bad form to use autorelease on an iOS device as the autorelease pool takes up quite a bit of overhead which might not be good on a mobile device

self.uiView = [[[UIView alloc] init] autorelease];

I've been toying with using the following pattern recently, which sets the property, and then calls release on the property (to decrease the reference counter on the property itself).

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

I've managed to use it on a few ViewControllers with no ill effects, but is this valid code, or am I missing something which makes it a bad idea?

jklp
  • 2,091
  • 2
  • 23
  • 37
  • possible duplicate of [Why shouldn't I use the getter to release a property in objective-c?](http://stackoverflow.com/questions/7262268/why-shouldnt-i-use-the-getter-to-release-a-property-in-objective-c) – albertamg Sep 01 '11 at 11:11
  • possible duplicate of [Objective-C: alloc of object within init of another object (memory management)](http://stackoverflow.com/questions/2818254/objective-c-alloc-of-object-within-init-of-another-object-memory-management) – jscs Sep 01 '11 at 19:00
  • Also very closely related to: http://stackoverflow.com/questions/7017046/objective-c-newbie-question-about-allocation-retain-and-release/7017089#comment-8380294 http://stackoverflow.com/questions/3722998/objective-c-memory-management-question – jscs Sep 01 '11 at 19:01

5 Answers5

1

If the implementation of the property getter is simply to return the reference to the underlying ivar, then it is perfectly equivalent and you simply decrease the retain count of the allocated object.

On the other hand, if you can't be sure what the getter does (what if it returns something else than the ivar, e.g. some calculated result etc.), it may be dangerous.

Tomas Vana
  • 18,317
  • 9
  • 53
  • 64
  • 1
    +1. You can also have properties without ivars, making this a dangerous pattern. And releasing objects returned by getters should be avoided. – hwaxxer Sep 01 '11 at 10:44
1

The property getter is a method, and it does not have to return an ivar, it may actually get its return value anywhere, so you could release that, but it could be an autoreleased value already. If that is the case, you're in trouble.

IOW, if a property getter would do something like (not usual, but possible and valid):

- (NSString *) helloString
{
    return [[myStringIVar copy] autorelease];
}

and you do:

[self.helloString release];

then you failed in two ways:

  • You did not release the ivar you wanted to release
  • You release an autoreleased object

IMO, it is better to release the ivar directly:

[myStringIVar release];
Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
1

It's not valid, and even in the cases where it does work its a bit "ugly" the other two are just to fix the property's retain characteristic from making the retain count 2 after having an alloc already making the retain count 1.

I tend to do what you described in the first example or the following.

in my @interface

@property (nonatomic, retain) UIView *uiView;

in my @implementation

@synthesize uiView = _uiView;

then when I setup the property.

_uiView = [[UIView alloc] init];
crackity_jones
  • 1,077
  • 2
  • 13
  • 16
  • No, I'm right in every respect. In fact it has occurred to me that releasing the object returned by a property getter is a breach of the memory management rules. – JeremyP Sep 01 '11 at 19:52
  • Hey that's what I'm looking for, I wish I could accept though your answer doesn't technically answer my question. I'll upvote though for a good solution :) – jklp Sep 02 '11 at 22:32
1

No. It's not valid.

It will probably work on most retain properties but not necessarily. It will probably break on copy properties and assign properties.

Properties are just a pair of methods, one of which sets an abstract entity and one which gets it. There is absolutely no guarantee in general that the getter will give you the exact same object that you just passed to the setter. For instance, if you pass a mutable string to an NSString copy property, you definitely won't get back the same object.

Use either of the first two patterns. The first one does not waste anything. It is likely the local variable will only ever exist in a register. The overhead of the second will only last as long as the next autorelease pool drain and is only a few bytes (bear in mind that the actual object will last as long as self in any case).

JeremyP
  • 84,577
  • 15
  • 123
  • 161
0

Thinking in terms of the reference counter, nothing is wrong with calling release using the property value. However, there are a few things, which I (personally) would dislike:

The property syntax is really just syntactic sugar for method calls. So, what your code really looks like, is

[self setUiView: [[UIView alloc] init]];
[[self uiView] release];

Another thing here might be more due to me thinking in strange ways, but I like to think of the reference counts as actually being related to references. A local variable holding a pointer to my object is such a reference. Having it present in the code reminds me, that I have something to do in order to clean things up properly (or, if not, at least write a short comment, why I don't have to clean up).

Directly going through the property forces me to think in terms of reference counts instead, which I don't like.

Dirk
  • 30,623
  • 8
  • 82
  • 102