What is the new pattern for releasing self with automatic reference counting?

automatic-ref-counting, memory-management, nscoder, objective-c

Solution

As noted, you cannot write `[self release];`. Additionally, `awakeAfterUsingCoder:` is not an initializer -- you may not reassign `self`.

Wouldn't this leak?

Yes. Proved in program below.

Or should I just trust the NSCoder object to release the original object for me?

No.

One approach to avoid the leak exists below -- I would not call it "the new pattern", just the first approach that came to mind. It involves an explicit release of `self` and in this case an explicit retain of the result:

#import <Foundation/Foundation.h>

@interface MONBoolean : NSObject < NSCoding >

- (id)initWithBool:(bool)pBool;

- (bool)isTrue;
- (bool)isFalse;

@end

static NSString * const MONBoolean_KEY_value = @"MONBoolean_KEY_value";

@implementation MONBoolean
{
    bool value;
}

- (id)initWithBool:(bool)pBool
{
    self = [super init];
    if (0 != self) {
        value = pBool;
    }
    return self;
}

- (bool)isTrue
{
    return true == value;
}

- (bool)isFalse
{
    return false == value;
}

- (NSString *)description
{
    return [[NSString alloc] initWithFormat:@"<%s:%p> : %s", object_getClassName(self), self, self.isTrue ? "true" : "false"];
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeBool:value forKey:MONBoolean_KEY_value];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (0 != self) {
        value = [aDecoder decodeBoolForKey:MONBoolean_KEY_value];
    }
    return self;
}

- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
    const bool b = value;
    // cannot reassign self outside of an initializer.
    // if not released, will result in a leak:
    CFRelease((__bridge const void*)self);
    MONBoolean * result = [[MONBoolean alloc] initWithBool:b];
    // now we have to retain explicitly because this is
    // an autoreleasing method:
    CFRetain((__bridge const void*)result);
    return result;
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        MONBoolean * a = [[MONBoolean alloc] initWithBool:true];
        NSData * data = [NSKeyedArchiver archivedDataWithRootObject:a];
        MONBoolean * b = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        NSLog(@"%@", b);
    }
    system("leaks NAME_OF_PROCESS_HERE");
    return 0;
}

Problem

Using the NSObject method `-(id)awakeAfterUsingCoder:(NSCoder *)decoder` as an example, the documentation says: Allows an object, after being decoded, to substitute another object for itself. For example, an object that represents a font might, upon being decoded, release itself and return an existing object having the same font description as itself. In this way, redundant objects can be eliminated. Normally you would do ``` [self release]; return substitutedObject; ``` With ARC you have to leave this line out. Wouldn't this leak? Or should I just trust the NSCoder object to release the original object for me? If so why would you have to explicitly release self with non-ARC code in the first place? I don't think `self = nil` is correct in light of what the compiler documentation says about self: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#misc.self

Original source