Objective c 目标C——init是一个不适合实施工厂的地方吗?
我实现了旧的init-as-a-factory模式,但在一个特定的情况下(但不是其他情况!)我从分析器得到了关于内存泄漏的警告。事实上,看看规则,可以返回+1-retain-count对象的是Objective c 目标C——init是一个不适合实施工厂的地方吗?,objective-c,Objective C,我实现了旧的init-as-a-factory模式,但在一个特定的情况下(但不是其他情况!)我从分析器得到了关于内存泄漏的警告。事实上,看看规则,可以返回+1-retain-count对象的是alloc,而不是init 看来: 严格地说,释放self并从init返回新对象是违反规则的 互联网上的许多地方都在推广这项技术,由于alloc/init的串联特性,这项技术确实有效 分析人员有时对此抱怨,有时则不抱怨 所以。。。我们一直都在做错事吗?正如gaige所说,如果您发布一段代码而不是解释,就会更
alloc
,而不是init
看来:
self
并从init
返回新对象是违反规则的所以。。。我们一直都在做错事吗?正如gaige所说,如果您发布一段代码而不是解释,就会更加清楚 无论如何,您可以将工厂移动到类方法,这样就不会有任何问题。我的意思是这样的:
MyClass* instance = [MyClass instanceWithParameters:params];
@interface MyClass
+ (MyClass*) instanceWithParameters:(ParamType)params;
@end
您可以像这样实现
init
,它应该释放self
,以平衡alloc
调用中的保留计数
- (id)initWithSomething:(id)something
{
[self release]; // don't need this line for ARC
self = nil;
return [[PrivateSubClass alloc] initWithSomething:something];
}
如果经常将
init
作为工厂方法来实现,这是非常困难的。e、 g.NSArray
,NSDictionary
,NSString
如果不知道是什么代码导致了分析器的行为,很难说清楚,但一般来说,这里有两种编译器友好的方法来定义init/factory方法
经典alloc/init
用法
这将生成一个保留计数为+1的实例。在ARC下,这将自动正确管理,因为它遵循NARC规则(新建、分配、保留、复制)。
出于同样的原因,在弧前环境中,它必须由客户端显式释放
自定义工厂方法
弧
弧前
用法
在ARC和pre-ARC中,该方法都返回一个自动释放的实例(在pre-ARC实现中,这显然更明确),而不必由客户机管理
评论
- 您可能已经注意到
关键字。这是由Clang引入的一个便利工具,它在实现您自己的构造函数/工厂方法时将编译器变成一个好朋友。我写了关于这个主题的文章,可能与你有关instancetype
- 工厂方法是否优于
方法仍有争议。从客户机的角度来看,如果您仔细遵循命名约定,在ARC下不会有太大区别,即使我个人倾向于在接口中公开工厂方法,而只在内部实现自定义init
方法(正如我在上面的示例中所做的那样)。这与其说是一个实际问题,不如说是一个风格问题init
MyClass*
。其名称必须以new
或alloc
开头,以便ARC知道它返回的对象的保留计数为+1。而MyClass*
会更好;)类工厂方法不以new或alloc开头。它们通常以类名开头。例如,在NSString中使用stringWithFormat:in NSString,或在NSNumber中使用numberWithBool:in NSNumber.yeah,在使用c而不是objective-c几个月后,忘记添加*
- (instancetype)initWithParameter:(id)parameter {
if(self = [super init]) {
_parameter = parameter;
}
return self;
}
MyCustomClass * myInstance = [[MyCustomClass alloc] initWithParameter:foo];
+ (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];