如上所述,您不能编写[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;
}
你能澄清为什么你必须明确保留结果吗?这当然会击败ARC的目的。感谢您回答所有其他问题。 – jamesmoschou 2012-04-23 09:24:46
@莫西欢迎您。是的 - 我最初忽略了那个细节。原因是'awakeAfterUsingCoder:'返回一个非拥有(或自动释放)的引用。因此,ARC会为我们的返回值插入一个引用计数递减量。我们想要做的是有效地将参考从一个对象转移到另一个对象。我用仪器运行它 - 没有泄漏。没有僵尸。如果没有明确的保留,僵尸会被发送。没有明确的释放 - 泄漏。自己尝试一下(把'@ autorelease'块放在'while(1)')中。 – justin 2012-04-23 09:49:58
你可以用'__attribute __((objc_method_family(init)))'方法使该方法成为'init'家族的成员,然后重新指派'self'吗? – 2012-05-29 21:55:32