【问题标题】:RetainCycle with Globals带全局变量的 RetainCycle
【发布时间】:2015-10-06 13:49:15
【问题描述】:

假设在 iOS 中我们有:

在 W2AppDelegate.m 中:

全局视图控制器 *globalVc; - (BOOL)应用程序:(UIApplication *)应用程序 didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... }

在 SomeOtherViewController.m 中:

- (void)viewDidLoad { [超级视图DidLoad]; [globalVc doSomething^{ [globalVc.someVariable doSomethingElse]; // 这里有保留循环吗? }]; }

这里有一个保留循环,因为我们在块内有一个对 globalVc 的强引用。

globalVc -> 块 -> globalVc

【问题讨论】:

  • 我想下面的每个人都在说这个:“globalVc -> block -> globalVc”是一个循环,但这取决于:“globalVc -> block”在你的代码中是真的,这还不清楚从问题。

标签: ios objective-c objective-c-blocks retain-cycle


【解决方案1】:

这里有一个保留循环,因为我们在块内有一个对 globalVc 的强引用。

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

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

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

【讨论】:

    【解决方案2】:

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

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

    如果您只是将它用于执行诸如执行块之类的任务,并且从不将其内容视图显示到屏幕上,那么您可能应该将该类设置为视图控制器以外的东西。

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

    这样的访问器函数
    +(Utils *) sharedUtils;
    

    返回一个指向 Utils 单例的指针。这比使用你正在做的全局更干净。

    【讨论】:

      【解决方案3】:

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

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

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


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

      【讨论】:

      • globalViewController 在这种情况下是一个单例。
      • 那么从技术上讲,保留周期不是问题,因为无论如何单例都会在程序的生命周期中存在。但重要的是要了解何时/为什么会有保留周期,因为有周期是不好的做法
      • 所以从技术上讲,无论是否存在问题,都有一个保留周期?
      • 在这种特殊情况下,请参阅Kazuki Sakamoto 的答案。因为它是全局变量,所以没有复制。
      猜你喜欢
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-12
      相关资源
      最近更新 更多