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?
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.
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:
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];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With