On Jun 23, 2009, at 4:47 AM, Graham Cox wrote:

On 23/06/2009, at 6:39 AM, Daniel Torrey wrote:

I'm looking at some sample iPhone code, and in the app delegate's applicationDidFinishLaunching method, I see

        // Set up the view controller
MyViewController *aViewController = [[MyViewController alloc] initWithNibName:@"HelloWorld" bundle:[NSBundle mainBundle]];
        self.myViewController = aViewController;
        [aViewController release];

I'm a little confused - I see an allocation, followed by an assignment, followed by a release. I think that the assignment is really a call to a setter - the myViewController field is created automagically using the @property/@synthesize syntax.

Since a release was sent to aViewController, what keeps that object from being nuked at the end of the run loop? There must be another retain happening somewhere, right?

Have a look at the definition for the property myViewController - it should include the 'retain' attribute, which tells you that the object is retained when it is assigned. In which case, it won't be nuked.

I don't think you can see the code generated by @synthesise, as it probably doesn't exist as Objective-C anywhere - but you can disassemble it. I could be wrong though...

--Graham

Apropos the question raised by Daniel and Graham's response, and to help other beginners, I'd like to relate a little true story that happened to me just yesterday.

In the iPhone app I'm writing, I was doing some text processing on the contents of a text field that the user can edit and in several places I had the same piece of code:

[textFieldPreviousContent release];
 textFieldPreviousContent = [textField.text retain];

So, I decided to make textFieldPreviousContent a property and dutifully declared

@property (readwrite, nonatomic, retain) NSString* textFieldPreviousContent;

in the header file and then synthesized it in the source file, like so:

@synthesize textFieldPreviousContent;

So far so good. I then replaced all the

[textFieldPreviousContent release];
 textFieldPreviousContent = [textField.text retain];

sections with the much simpler

textFieldPreviousContent = textField.text;

the motivation being that I would not have to remember every time to release textFieldPreviousContent nor to retain textField.text.

Ok, great, so now I built and ran and... my app crashed.

Huh? Wait... it was working fine before. Hmm... let me see. Property declared correctly... it's readwrite... check. It's retained... check. Property synthesized correctly... check.

What the heck???

So, after I scratched my head silly for several minutes, it suddenly came to me. If I'm going to use a property, I *must* refer to it as object.property rather than simply as property. In the specific example I had, I should not have replaced all those repeated chunks of code with

textFieldPreviousContent = textField.text;

but with

self.textFieldPreviousContent = textField.text;

Using

textFieldPreviousContent = textField.text;

meant that I was bypassing the very memory management I thought I was getting for free by turning textFieldPreviousContent into a property. Of course, my mistake implied that a) I was leaking the string pointed to by textFieldPreviousContent and b) I was not retaining the string returned by textField.text. And since that string is returned to me auto-released, textFieldPreviousContent ended up pointing to a memory location that was no longer valid by the time I used its contents. No wonder my app crashed.

So, to all beginners out there, whenever you define a property, remember always to refer to it, in its own class, by self.property - at least when setting its value. It may be ok (depending on what you're doing) to refer to it simply by property when *getting* its value, but if the property is backed by an instance variable that is an object (rather than a scalar type), it's *essential* that you refer to it by prepending self when *setting* its value, or you'll not be doing the memory management that you think you're doing.

Wagner
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to