objective-cmemory-managementthree20

Setting object to nil after release -- TT_RELEASE_SAFELY


I have started to study Three20 and I have a simple question about TT_RELEASE_SAFELY Up till now I like to write code in this way:

UILabel *lab = [[UILabel alloc] initWithFrame:rect];
[self.view addSubview:lab];
[lab release];

Here I think the main pool is responsible to free the memory of lab.

Now I have found TT_RELEASE_SAFELY which is defined like so:

#define TT_RELEASE_SAFELY(__POINTER) { [__POINTER release]; __POINTER = nil; }

As you can see, after release, it sets the object to nil.

I'd like to know the difference between the two ways and which way is better.

Thanks.


Solution

  • Sending a message to nil is valid in Objective-C. Sending a message to a deallocated object is not.

    Sending a message to a deallocated object:

    id obj = [[MyClass alloc] init];
    [obj release];
    [obj doSomething]; // Crash!

    Sending a message to nil:

    id obj = [[MyClass alloc] init];
    [obj release], obj = nil;
    [obj doSomething]; // Valid

    Assigning nil to a variable after an object has been deallocated is controversial because it can prevent you from realizing that something is wrong. Sedate Alien's example:

    [controlCenter dealloc];
    ...
    float timeLeft = [controlCenter timeToWaitBeforeBombDetonation];
    

    This code will crash since controlCenter has been deallocated. As a result this defect will be detected and fixed early.

    [controlCenter dealloc], controlCenter = nil;
    ...
    float timeLeft = [controlCenter timeToWaitBeforeBombDetonation];
    

    This code will assign 0.0 to timeLeft which appears to be a valid wait time even though controlCenter is nil.


    Take the above with a grain of salt, since if you are writing an Objective-C app, you are probably more concerned with keeping your users happy by avoiding crashes than destroying cities. If the latter is a concern, you should probably be using a type-safe language like Ada.