Retain Still Matters

By: Jeremy W. Sherman. Published: . Categories: obj-c arc.

I recently received a question about this particular bit of code:

//cc -Wall -Wextra -Weverything -g -framework Foundation -fobjc-arc \
//nsstring-weak.m -o nsstring-weak
#import <Foundation/Foundation.h>

int
main(void)
{
/* nsstring-weak.m:7:22:
 * warning: assigning retained object to weak variable; object will be released
 * after assignment [-Warc-unsafe-retained-assign] */
    NSString *__weak stringInit = [[NSString alloc] initWithFormat:@"Lewis"];
    NSLog(@"stringInit: %@", stringInit);  // stringInit logs as (null)

    NSString *__weak stringLiteral = @"String";
    NSLog(@"stringLiteral: %@", stringLiteral);

    NSString *__weak stringFormat = [NSString stringWithFormat:@"SomeString"];
    NSLog(@"stringFormat: %@", stringFormat);
}

As the comment points out, clang warns about the first assignment, the one to stringInit, but not to any of the others.

You might read this as, “Assigning to weak blah blah blah released after assignment.” OK, well, now that you point it out clang, duh. I’ll fix that.

But then you look at the other two assignments: Why is clang OK with these?

Here’s the warning again:

nsstring-weak.m:7:22: warning: assigning retained object to weak variable; object will be released after assignment [-Warc-unsafe-retained-assign]

It turns out the real keyword in that message is the one you very well might have glossed over the first time: retained.

That’s the difference between the three object references:

So you can still run into differences between objects returned from an alloc–init pair and those returned autoreleased under ARC, even in a bit of wotsit-wotsit code as minimal as this.

If you’d like to learn more, the nearly definitive reference on ARC lives in the Clang docs.

The actually definitive reference, of course, is clang’s source code coupled with the Obj-C runtime code.