skip to Main Content

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


  1. According Apple documentation, the method requestTrackingAuthorization has an escaping closure parameter:

    enter image description here

    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 that ATTrackingManager is a class that lives as long as the whole application lives so it can capture self 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 an ATTrackingManager won’t change in next releases.

    Login or Signup to reply.
  2. 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 the ATTrackingManager, so there’s no loop by having ATTrackingManager hold a strong reference to self. That is definitely not a reason to use or not use weak self here.

    The reason to use or not use weak self here is based on what you want to happen if whatever self refers to is otherwise released. Should GADBannerView be created, or not? If this block should not be run in that case, then using weak self enables you to check if self is gone. If self should never be released before this callback, then use strong self 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. Adding weak 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search