如前所述,您不能编写[self release];
. 此外,awakeAfterUsingCoder:
它不是初始化器——您不能重新分配self
.
这不会泄露吗?
是的。在下面的程序中证明。
还是我应该相信 NSCoder 对象会为我释放原始对象?
不。
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;
}