我实现了旧的init作为工厂模式,但在一个特定的情况下(而不是其他!)我收到分析器关于内存泄漏的警告。事实上,看看可可内存管理政策规则,可以返回+1保留计数对象的是alloc,而不是init。
因此,看来:
self并从init返回一个新对象是违反规则的。所以..。我们一直都在做错事吗?
发布于 2013-06-09 23:05:24
您可以这样实现init,它应该释放self以平衡alloc调用中的保留计数。
- (id)initWithSomething:(id)something
{
[self release]; // don't need this line for ARC
self = nil;
return [[PrivateSubClass alloc] initWithSomething:something];
}如果经常将init作为工厂方法来实现的话。例如NSArray,NSDictionary,NSString
发布于 2013-06-09 14:02:03
正如gaige所说,如果你发布一段代码而不是解释,它会更加清晰。
无论如何,您可以将您的工厂移到类方法中,这样您就不会有这样的问题了。我的意思是这样的:
MyClass* instance = [MyClass instanceWithParameters:params];
@interface MyClass
+ (MyClass*) instanceWithParameters:(ParamType)params;
@end发布于 2013-06-10 00:28:27
在不知道导致分析器行为的代码是什么的情况下,很难判断,但作为一般规则,这里有几种定义init/工厂方法的编译器友好的方法。
经典alloc/init
- (instancetype)initWithParameter:(id)parameter {
if(self = [super init]) {
_parameter = parameter;
}
return self;
}用法
MyCustomClass * myInstance = [[MyCustomClass alloc] initWithParameter:foo];这将产生一个具有+1保留计数的实例。在ARC下,这将被自动正确地管理,因为它遵循NARC规则(New,Alloc,rule,Copy)。出于同样的原因,在预ARC环境中,客户端必须显式地发布它.
自定义工厂法
圆弧
+ (instancetype)canIHazInstanceWithParameter:(id)parameter {
return [[self alloc] initWithParameter:parameter]; // assuming -initWithParameter: defined
}预弧
+ (instancetype)canIHazInstanceWithParameter:(id)parameter {
return [[[self alloc] initWithParameter:parameter] autorelease]; // assuming -initWithParameter: defined
}用法
MyCustomClass * myInstance = [MyCustomClass canIHazInstanceWithParameter:foo];在ARC和预ARC中,该方法都返回一个自动释放的实例(在预ARC实现中这显然更明确),它不需要由客户端管理。
备注
instancetype关键字。这是Clang引入的一个方便的语言延伸,在实现您自己的构造函数/工厂方法时,它将编译器变成一个好朋友。我写了关于这个问题的文章,这可能和你有关。init方法是值得商榷的。从客户端的角度来看,它在ARC下没有多大区别,前提是您要小心遵循命名约定,即使我个人倾向于在接口中公开工厂方法,而只在内部实现自定义init方法(正如我在上面的示例中所做的那样)。与其说这是一个实际的问题,不如说是一个风格的问题。https://stackoverflow.com/questions/17009872
复制相似问题