块中的[self new]是否会创建强大的参考周期?

时间:2016-08-26 14:05:00

标签: objective-c memory-management singleton automatic-ref-counting objective-c-blocks

我正在创建单身,如下所示:

static MyType* shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    shared = [self new];
});
return shared;

我知道该块中的代码将执行一次,此时self将为nil,因此[self new]将等于[MyType new]。但是当我在一个非单身目的的块中调用[self new]并且可以多次调用时,我正在考虑情况。

[self new]会像[MyType new]那样行事,还是会阻挡self?这是使用MyType创建[self new]的新实例的正确方法吗?使用[self new]代替[MyType new]有什么好处?

3 个答案:

答案 0 :(得分:1)

没有。没有“循环”。该块捕获对类对象的强引用(这是self指向的对象,因为它是类方法)。类对象不包含对块的任何引用。

答案 1 :(得分:0)

是的,self被块捕获,但self未捕获该块,因此没有发布周期。无论如何,由于self指向MyType的类对象,并且因为类对象永远不会被释放,所以在这种特定情况下你不应该担心保留周期。

答案 2 :(得分:0)

  

[self new]会像[MyType new]一样,还是一个块会捕获自己?

正如其他答案所述,这不是保留周期。但是,请记住,self指向类对象,而类对象不是ARC的对象:它们具有永恒的生命时间。

  

使用[self new]创建新的MyType实例是否正确?

这是更好的方式。见下文。

  

使用[self new]代替[MyType new]有什么好处?

在类的实现中,您应该几乎总是使用self而不是MyType。 (但是你的代码是由于静态变量而无法做到这一点的罕见例子之一。)

原因是,子类可以使用该代码。如果将具体类型放在代码中,则必须覆盖每个创建方法,这会导致很多代码并触发破坏的基类问题。

示例:

@implementation BaseClass
+ (instancetype)new…
{
  BaseClass *instance = [BaseClass new];
  …
}
@end

@interfac Subclass : BaseClass
…
@end

这已经破了,因为......

id instance = [Subclass new…];

...将创建子类的实例。

您必须覆盖new…,还有其他问题:

@implementation Subclass
+(instancetype)new…
{
  /* Subclass *instance = [super new]; Does NOT work*/
  … Complete re-implementation of +new… (BaseClass)
}