前述のとおり、書き込みはできません[self release];
。さらに、awakeAfterUsingCoder:
は初期化子ではありません。再割り当てはできませんself
。
これは漏れませんか?
はい。以下のプログラムで証明されています。
それとも、NSCoder オブジェクトを信頼して元のオブジェクトを解放する必要がありますか?
いいえ。
リークを回避するための 1 つのアプローチを以下に示します。これを「新しいパターン」とは呼びません。頭に浮かんだ最初のアプローチにすぎません。これには、結果の明示的な解放が含まれます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;
}