前述のように、[self release];
と書くことはできません。さらに、awakeAfterUsingCoder:
はで、初期化ツールではありません - self
を再割り当てすることはできません。
このリークはありませんか?
はい。以下のプログラムで証明されています。
NSCoderオブジェクトを信頼して元のオブジェクトを解放するだけでいいですか?漏れを避けるために
号
一つのアプローチは、以下の存在 - 私が頭に浮かんだだけで最初のアプローチ、「新しいパターン」それを呼び出すことはありません。それはself
の明示的な解放を含み、この場合には、明示的なは、結果の保持:同様の問題は、Mac OS X上NIBトップレベルのオブジェクトのコンテキストで発生し
#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
@moshyよろしくお願いします。はい - 私は最初、その細部を見落としました。その理由は 'awakeAfterUsingCoder:'は所有していない(または自動リリースされた)参照を返してしまうからです。そのため、ARCは私達の戻り値に対してref-count減少を挿入します。私たちがしたいことは、あるオブジェクトから別のオブジェクトへの参照を効果的に*転送することです。私は楽器でそれを走らせました - 漏れはありません。ゾンビはありません。明示的な保持なしでは、ゾンビがメッセージされるだろう。明示的なリリースなしに - リーク。自分自身で試してみてください( '@ autorelease'ブロックを' while(1) 'に入れてください)。 – justin
メソッドを '__attribute __((objc_method_family(init)))'で 'init'ファミリのメンバにしてから' self'を再割り当てできますか? –