RetainCycle 与 Globals

RetainCycle with Globals

假设 iOS 我们有:

在W2AppDelegate.m中:

GlobalViewController *globalVc;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...

}

在SomeOtherViewController.m中:

- (void)viewDidLoad {
    [super viewDidLoad];

    [globalVc doSomething^{
       [globalVc.someVariable doSomethingElse]; // Is there a retain cycle here?
    }];
}

这里是否有循环引用,因为我们在块中有对 globalVc 的强引用。

globalVc -> 区块 -> globalVc

忽略糟糕的设计 - 视情况而定。

如果您在 ivar 中存储一个块,并且该块引用了 ivar 所在的对象,那么您确实会得到一个保留周期 - 见下文:

如果您实际上并没有存储该块,而只是调用该块,那么您最终可能根本不会使用任何额外的保留 - 见下文


不清楚您的 GlobalViewController 是单例还是可以更新的全局引用。如果它是一个单例,那么保留周期就不那么重要了,因为您希望该对象在程序的整个生命周期内都存在。

您已将 globalVc 变量定义为应用委托中的全局变量。当您创建 GlobalViewController 时,它将在您的应用程序的生命周期内持续存在。有时您希望视图控制器永远存在。

这不是一个保留周期,但它确实会在您的应用程序的生命周期内占用内存。

如果您仅将它用于执行块等任务,并且从不在屏幕上显示它的内容视图,您可能应该将 class 设为视图控制器以外的东西。

我有时会创建一个 Utils 单例,用于提供应用程序范围的实用程序功能。我写了一个访问函数,比如

+(Utils *) sharedUtils;

那个 returns 指向 Utils 单例的指针。这比像你这样使用全局更干净。

Is there a retain cycle here since we have a strong reference to globalVc inside the block.

没有。因为块只捕获局部变量。

[globalVc doSomething^{
   [globalVc.someVariable doSomethingElse]; // Is there a retain cycle here?
}];

globalVc 未被块捕获,因为 globalVc 是全局变量。这里没有局部变量,所以块不捕获任何对象,因此块根本不保留任何对象。