NSURLSession 应该是弱 属性

Should NSURLSession be a weak property

我正在调查内存泄漏,通过使用 Malloc 选项,我们的 class 看起来像这样:

SessionManager class有

@property(nonatomic, strong) NSURLSession *urlSession;

- (instancetype)initWithConfiguration(NSURLSessionConfiguration)configuration {
    if (self = [super init]) {
    _urlSession = [NSURLSession sessionWithConfiguration:configuration delgate: self delegateQueue:_sessionQueue];


    }

    return self;
}

我不确定如何阅读它,除非我能猜到,它是 NSURLSession 持有 SessionManager 以及 SessionManager 对 NSURLSession 的强引用。 NSURLSession 的 属性 应该是 weak 还是 unowned?

其次,如果是,那是什么原因呢?

URLSession documentation 所说:

The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session.

因为你的会话管理器对会话有强引用,而会话对它的委托有强引用,所以你有一个强引用循环,直到应用程序终止或会话无效才解决。

如果你想避免这种情况,我不会对 URLSession 使用弱引用。相反,我倾向于将 URLSession 委托方法移动到独立的委托对象,而不是将它们保留在 SessionManager 对象中。这将避免强引用循环。它也可能是一种更简洁的设计,与 "single responsibility principle."

保持一致

但应该认识到,这并没有真正改变应用程序的基本内存特性。该应用程序大概维护对会话管理器的引用,会话管理器维护对会话的引用,会话维护对委托对象的强引用。在会话失效之前,与委托对象关联的内存不会被释放。但它避免了强引用循环,否则可能会使您的 "debug memory graph" 分析变得混乱。

你的假设是正确的。来自 documentation:

Discussion

This delegate object is responsible for handling authentication challenges, for making caching decisions, and for handling other session-related events. The session object keeps a strong reference to this delegate until your app exits or explicitly invalidates the session. If you do not invalidate the session, your app leaks memory until it exits.

这基本上就是你写的意思。你有双面强参考循环。正如您所说,您可以通过将 urlSession 设置为 weak 参考来打破它。然而,这可能(但不是必需的)会导致不良的副作用,例如在创建 urlSession 后立即丢失它,因为没有对象捕获对它的强引用。

我会建议

  • 确保这部分代码确实能产生一些重大影响 内存泄漏(因为现在它看起来像一种简单的单例,不应该占用太多内存)
  • 如果它真的会导致内存泄漏 - 重新考虑您的体系结构,以便您可以 invalidate sessions

P.S.

如果您的主要目标是调查内存泄漏,那么在调试内存图以分析对象计数器和 Xcode 的提示时查看 Xcode 的左侧面板会很有帮助(紫色矩形中的感叹号)。