使用NSObject方法-(id)awakeAfterUsingCoder:(NSCoder *)decoder
作为示例,文档说:
允许对象在解码后替换另一个对象 为了自己。例如,表示字体的对象可能会在 被解码,释放自己并返回一个现有的对象 与其本身相同的字体描述。这样,冗余对象就可以了 消除。
通常你会这样做
[self release];
return substitutedObject;
使用ARC,你必须离开这条线。这不会泄漏吗?或者我应该只相信NSCoder对象为我发布原始对象?如果是这样的话,为什么你必须首先用非ARC代码明确释放self?
根据编译器文档中关于self的内容,我认为self = nil
不正确:http://clang.llvm.org/docs/AutomaticReferenceCounting.html#misc.self
答案 0 :(得分:4)
在Mac OS X上的NIB顶级对象的上下文中出现了类似的问题。Resource Programming Guide说:
如果文件所有者不是
NSWindowController
或NSViewController
的实例,那么您需要自己减少顶级对象的引用计数。通过手动引用计数,可以通过向顶级对象发送release
消息来实现此目的。你无法用ARC做到这一点。相反,您将对顶级对象的引用转换为Core Foundation类型并使用CFRelease
。
所以,这种技术也可以在这种情况下使用。 CFRelease((__bridge CFTypeRef)self);
答案 1 :(得分:2)
如上所述,您无法撰写[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;
}
答案 2 :(得分:0)
我相信ARC非常聪明,可以跟踪所有对象。所以你应该能够对内存没有任何说法,应用程序将在不再使用时释放该对象。通过泄漏探查器运行它,以防万一,但它应该没问题。