使用自动引用计数释放自我的新模式是什么?

jam*_*hou 7 memory-management objective-c nscoder automatic-ref-counting

以NSObject方法-(id)awakeAfterUsingCoder:(NSCoder *)decoder为例,文档说:

允许对象在解码后替换另一个对象.例如,表示字体的对象在解码时可以释放自身并返回具有与其自身相同的字体描述的现有对象.通过这种方式,可以消除冗余对象.

通常你会这样做

[self release];
return substitutedObject;
Run Code Online (Sandbox Code Playgroud)

使用ARC,你必须离开这条线.这不会泄漏吗?或者我应该只相信NSCoder对象为我发布原始对象?如果是这样,为什么你必须首先用非ARC代码明确释放自己?

self = nil根据编译器文档中关于self的内容,我认为不正确:http://clang.llvm.org/docs/AutomaticReferenceCounting.html#misc.self

jus*_*tin 2

如前所述,您不能写[self release];. 此外,awakeAfterUsingCoder:不是初始化器——您不能重新分配self

这不会泄露吗?

是的。在下面的程序中证明了。

或者我应该相信 NSCoder 对象为我释放原始对象?

不。

下面有一种避免泄漏的方法——我不会称之为“新模式”,只是想到的第一种方法。它涉及显式释放结果self,在本例中是显式保留结果:

#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;
}
Run Code Online (Sandbox Code Playgroud)