使用NSObject方法 – (id)awakeAfterUsingCoder:(NSCoder *)解码器作为示例,文档说:
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.
通常你会这样做
[self release]; return substitutedObject;
使用ARC,你必须离开这条线.这不会泄漏吗?或者我应该只相信NSCoder对象为我发布原始对象?如果是这样,为什么你必须首先用非ARC代码明确释放自己?
根据编译器文档中关于self的内容,我认为self = nil是不正确的:http://clang.llvm.org/docs/AutomaticReferenceCounting.html#misc.self
解决方法
如上所述,你不能写[self release];.另外,awakeAfterUsingCoder:不是初始化者 – 你可能不会重新分配自己.
Wouldn’t this leak?
是.在下面的程序中证明.
Or should I just trust the NSCoder object to release the original object for me?
没有.
下面是一种避免泄漏的方法 – 我不会称之为“新模式”,这只是我想到的第一种方法.它涉及自我的显式释放,在这种情况下显式保留结果:
#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; }