在不知道导致分析器行为的代码是什么的情况下,很难判断,但作为一般规则,这里有几种编译器友好的方法来定义初始化/工厂方法。
经典分配/初始化
- (instancetype)initWithParameter:(id)parameter {
if(self = [super init]) {
_parameter = parameter;
}
return self;
}
用法
MyCustomClass * myInstance = [[MyCustomClass alloc] initWithParameter:foo];
这将产生一个具有 +1 保留计数的实例。在 ARC 下,这将自动得到妥善管理,因为它遵循 NARC 规则(新建、分配、保留、复制)。出于同样的原因,在 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 和 pre-ARC 中,该方法都返回一个自动释放的实例(这在 ARC 前的实现中显然更加明确),它不必由客户端管理。
评论
您可能已经注意到instancetype
关键字。这是 Clang 引入的一个方便的语言扩展,在实现你自己的构造函数/工厂方法时,它把编译器变成了一个亲爱的朋友。我写了一篇关于这个主题的文章,可能与你有关。
工厂方法是否比方法更可取init
是有争议的。从客户端的角度来看,它在 ARC 下没有太大区别,只要您仔细遵循命名约定,即使我个人倾向于在接口中公开工厂方法,而init
仅在内部实现自定义方法(就像我在上面的示例中所做的那样) . 这更多的是风格问题,而不是实际的实际问题。