Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Effect of 'myObj = [[[[MyClass alloc] init] autorelease] retain];'?

I've just downloaded the Facebook iOS SDK and I noticed that in the sample code that comes with the SDK whenever it creates an instance of the Facebook class it does it like this:

_facebook = [[[[Facebook alloc] init] autorelease] retain];

where _facebook is a member variable of the calling object (i.e. not a local variable).

Can anyone explain exactly what's the point of autoreleasing and then retaining it?

like image 235
filipe Avatar asked Aug 31 '10 20:08

filipe


2 Answers

It effectively does nothing beyond consuming some cycles and memory.

Or, more precisely, in a correctly written application, it does nothing. In an incorrectly written application, it might mask a bug by lengthening the lifespan of the _facebook object. However, it isn't a real fix.

I found a similar line of code in http://github.com/facebook/facebook-ios-sdk/blob/master/sample/DemoApp/Classes/DemoAppViewController.m If that is what you are referring to then, yes, it is nonsense.

like image 141
bbum Avatar answered Nov 14 '22 22:11

bbum


While it's possible that the code you found was just sloppy, that pattern DOES have a meaning.

"alloc, autorelease, retain" implies that the object is referenced in two places:

  • As a return value on the call stack (autorelease style)
  • By the FB SDK itself (the 'retain')

This matters if the two references can be released independently. For example, if the SDK can release its reference BEFORE the call stack has completed and drained the autorelease pool. Ok, this is pretty nuanced; what do I mean?

Consider these cases:

A) the actual code

_facebook = [[[[Facebook alloc] init] autorelease] retain];

_facebook now has a retain count of 2, and expects 2 calls to 'release': 1 from whoever called "retain", and 1 at some point in the future when the NSAutoreleasePool drains.

B) the simple "alternative" proposed (NOT equivalent)

_facebook = [[Facebook alloc] init];

_facebook has a retain count of 1 and will be destroyed when 'release' is called (potentially a big problem if the autorelease pool hasn't drained yet and the call stack is still using the object)

Why does this matter? Imagine some code like this:

@implementation (Thinger)
+(id) make_new_thing
{
    return my_copy_of_thing = [[[[Thing alloc] init] autorelease] retain];
}
+(id) forget_about_thing
{
    if (my_copy_of_thing != nil) {
        [my_copy_of_thing release];
        my_copy_of_thing = nil;
    }
}
@end


void foo() {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    id thing = [Thinger make_new_thing];
    [Thinger forget_about_thing];
    ...
    [thing useThing]; // implementation B would break here !
    [pool drain];
}
like image 28
Dave Dopson Avatar answered Nov 14 '22 21:11

Dave Dopson