How is a strong retain cycle possible with async or static calls?

杀马特。学长 韩版系。学妹 提交于 2019-12-13 05:14:20

问题


I am trying to grasp how I can recognize when a strong retain cycle is possible and requires me to use [weak/unowned self]. I've been burned by unnecessarily using [weak/unowned self] and the self was deallocated immediately before giving me a chance to use it.

For example, below is an async network call that refers to self in the closure. Can a memory leak happen here since the network call is made without storing the call it self into a variable?

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) {
  (data, response, error) in
  self.data = data
)

Here's another example using the NSNotificationCenter, where a call can be made later asynchronously:

 NSNotificationCenter.defaultCenter().addObserverForName(
        UIApplicationSignificantTimeChangeNotification, object: nil, queue: nil) {
            [unowned self] _ in
            self.refresh()
    }

My question is in what cases is a strong retain cycle possible? If I am making an asynchronous call or static call that references self in a closure, does that make it a candidate for [weak/unowned self]? Thanks for shedding any light on this.


回答1:


A retain cycle is a situation when two objects has a strong reference to each other.

You are working with static variables NSURLSession.sharedSession() & NSNotificationCenter.defaultCenter() and as you may remember:

A singleton object provides a global point of access to the resources of its class...You obtain the global instance from a singleton class through a factory method. The class lazily creates its sole instance the first time it is requested and thereafter ensures that no other instance can be created. A singleton class also prevents callers from copying, retaining, or releasing the instance.

https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/Singleton.html

Your "self" instance (like the others) doesn't have a strong reference to singletons objects and its closures too, that's why you don't have to worry about retain cycle in your case.

Check this great article for more details: https://digitalleaves.com/blog/2015/05/demystifying-retain-cycles-in-arc/




回答2:


In a nutshell:

The retain cycle can happen in two cases.

Case 1:

When two instances hold a strong reference to each other. You have to solve this by marking one of them as weak.

Case 2: (Which is related to your questions)

If you assign a closure to a property of a class instance and the body of that closure captures the instance.

In your two examples, no need to use weak self at all as NSNotificationCenter nor NSURLSession are properties to your class instance. (Or in other meaning, you don't have strong references to them)

Check this example where I have to use weak self:

[self.mm_drawerController setDrawerVisualStateBlock:^(MMDrawerController *drawerController, MMDrawerSide drawerSide, CGFloat percentVisible) {

    if (drawerSide == MMDrawerSideRight && percentVisible == 1.0) {
        [weakself showOverlayBgWithCloseButton:YES];
    }
    else{

        [weakself hideOverlayBg];
    }
}];

I have a strong reference to mm_drawerController and I assign a closure to it right?. inside this closure I want to capture self. So the closure will have a strong reference to self !! which is a disaster. In that case you will have a retain cycle. To break this cycle, use weak self inside the closure.



来源:https://stackoverflow.com/questions/37238720/how-is-a-strong-retain-cycle-possible-with-async-or-static-calls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!