I was wondering, how can I decide, whether [weak self]
is required in ATTrackingManager.requestTrackingAuthorization
, to prevent memory leak?
Without [weak self]
ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
// In this case, we instantiate the banner with desired ad size.
let bannerView = GADBannerView(adSize: GADAdSizeBanner)
self.bannerView = bannerView
bannerView.delegate = self
bannerView.adUnitID = Constants.BANNER_AD_UNIT_ID
bannerView.rootViewController = self
bannerView.load(GADRequest())
})
With [weak self]
ATTrackingManager.requestTrackingAuthorization(completionHandler: { [weak self] status in
guard let self = self else { return }
// In this case, we instantiate the banner with desired ad size.
let bannerView = GADBannerView(adSize: GADAdSizeBanner)
self.bannerView = bannerView
bannerView.delegate = self
bannerView.adUnitID = Constants.BANNER_AD_UNIT_ID
bannerView.rootViewController = self
bannerView.load(GADRequest())
})
How I can know, whether [weak self]
is required, to prevent memory leak?
2
Answers
According Apple documentation, the method
requestTrackingAuthorization
has an escaping closure parameter:An escaping closure is a closure that can go out of the scope where it was being used and live any time.
So if you don’t know inner realization of a
ATTrackingManager
, you’d better assume the worst. In this case the worst assumption is thatATTrackingManager
is a class that lives as long as the whole application lives so it can captureself
and hold it forever causing memory leaks.And despite in this case (as I checked) there is no memory leak, the general rule will be to use
weak self
, because you can’t be sure the realization of anATTrackingManager
won’t change in next releases.There absolutely is no retain loop here, and
weak
absolutely is not required in order to prevent a memory leak.self
has no reference to theATTrackingManager
, so there’s no loop by havingATTrackingManager
hold a strong reference toself
. That is definitely not a reason to use or not useweak self
here.The reason to use or not use
weak self
here is based on what you want to happen if whateverself
refers to is otherwise released. Should GADBannerView be created, or not? If this block should not be run in that case, then usingweak self
enables you to check ifself
is gone. Ifself
should never be released before this callback, then use strongself
to express that.In this case, you probably don’t want this screen to go away until the auth request finishes, so you should not use
weak
.As a rule, delegate-like closures that are called repeatedly need
weak self
since they generally have a retain loop that cannot be broken. "Callbacks" (i.e. things that are called exactly once) do not, because once the callback is executed, the closure should be released, and any loop will be broken.But who am I kidding? Few people think very much about the semantics, and just slap
[weak self]
on everything and that rarely is actually a problem, while the reverse can be a problem. Addingweak
everywhere isn’t "careful." It’s just sloppy. But it’s a sloppiness that works ok in practice. It’s just annoying to look at.