I'm investigating a memory leak and from using the Malloc option, it looks like a class that we have has this:
The class, SessionManager, has
@property(nonatomic, strong) NSURLSession *urlSession;
- (instancetype)initWithConfiguration(NSURLSessionConfiguration)configuration {
if (self = [super init]) {
_urlSession = [NSURLSession sessionWithConfiguration:configuration delgate: self delegateQueue:_sessionQueue];
}
return self;
}
I'm not sure how to read this, except if I could guess, it'd be the NSURLSession holds onto the SessionManager as well as the SessionManager having a strong reference to NSURLSession. Should the property for NSURLSession be weak or unowned?
Secondly, if so, what would the reason be for this?
Your assumption is right. From 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.
Which basically means exactly what you wrote. You have double-sided strong reference cycle. And as you said you could break it by setting urlSession
to be weak
reference. However this may (but not necessary) cause undesirable side effects like immediately losing your urlSession
after creating it since no object captures the strong reference to it.
I'd advice
P.S.
If your primary goal is to investigate memory leak it would be helpful to take a look at the left panel of Xcode while debugging memory graph to analyze object counters and Xcode's hints (exclamation marks in violet rectangles).
As URLSession
documentation says:
The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session.
Because your session manager has a strong reference to the session and the session has a strong reference to its delegate, you have a strong reference cycle, not unresolved until the app terminates or the session is invalidated.
If you want to avoid this, I would not use a weak reference to the URLSession
. Instead, I'd be inclined to move the URLSession
delegate methods to a stand-alone delegate object rather than keeping them in your SessionManager
object. This will avoid the strong reference cycle. It's potentially a cleaner design, too, in keeping with the "single responsibility principle."
But it should be recognized that this doesn't really change the fundamental memory characteristics of the app. The app presumably maintains reference to session manager, which maintains reference to the session, which maintains strong reference to the delegate object. The memory associated with the delegate object will not be released until the session is invalidated. But it avoids the strong reference cycle which may otherwise be cluttering your "debug memory graph" analysis.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With