如上所述,您不能編寫[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