不知道是哪段代码导致了分析器的行为,很难说,但通常来说,以下是一些编译器友好的定义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,Retain,Copy),它将被自动管理,因此可以正确地进行处理。
出于同样的原因,在ARC之前的环境中,客户端必须明确释放它。
自定义工厂方法
ARC
+ (instancetype)canIHazInstanceWithParameter:(id)parameter {
return [[self alloc] initWithParameter:parameter]; // assuming -initWithParameter: defined
}
Pre-ARC
+ (instancetype)canIHazInstanceWithParameter:(id)parameter {
return [[[self alloc] initWithParameter:parameter] autorelease]; // assuming -initWithParameter: defined
}
使用方法
MyCustomClass * myInstance = [MyCustomClass canIHazInstanceWithParameter:foo];
在 ARC 和 pre-ARC 中,该方法返回一个自动释放的实例(在 pre-ARC 实现中这更明确),无需由客户端管理。
备注
您可能已经注意到了 instancetype
关键字。这是 Clang 引入的一个方便的语言扩展,可将编译器变成实现自己的构造函数/工厂方法时的好朋友。我曾经写过一篇文章讨论这个问题,它可能与您有关。
工厂方法是否比 init
方法更可取是有争议的。从客户端的角度来看,在 ARC 下并没有太大区别,只要您仔细遵循命名约定,即使我个人倾向于在接口中公开工厂方法,而仅在内部实现自定义 init
方法(如上面的示例所示)。这更多是风格问题,而不是实际的实用问题。