异步或静态调用如何实现强保留周期?

时间:2016-05-15 13:11:42

标签: ios swift memory-management memory-leaks strong-references

我正在努力了解如何在可以实现强保留周期的情况下识别并要求我使用[weak/unowned self]。我被不必要地使用[weak/unowned self]而被烧伤,并且在给我机会使用之前,我们立即解除了自我。

例如,下面是一个异步网络调用,它引用了闭包中的self。可以在这里发生内存泄漏,因为网络调用是在没有将自己的调用存储到变量中的吗?

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

这是另一个使用NSNotificationCenter的示例,其中可以稍后异步调用:

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

我的问题是在什么情况下可以实现强大的保留周期?如果我在闭包中进行异步调用或静态调用,这会使它成为[weak/unowned self]的候选者吗?谢谢你对此有所了解。

2 个答案:

答案 0 :(得分:1)

简而言之:

保留周期可能发生在两种情况下。

案例1:

当两个实例相互强烈引用时。你必须通过将其中一个标记为弱来解决这个问题。

案例2 :(与您的问题有关)

如果为类实例的属性分配闭包,则该闭包的主体捕获实例。

在您的两个示例中,根本不需要使用弱自我,因为NSNotificationCenterNSURLSession属于您的类实例的属性。 (或者换句话说,你没有强烈的引用)

检查这个例子,我必须使用弱自我:

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

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

        [weakself hideOverlayBg];
    }
}];

我对mm_drawerController有一个强烈的引用,我给它分配了一个闭包吗?在这个闭包内我想捕捉自我。所以关闭将有一个强烈的自我参考!这是一场灾难。在这种情况下,您将有一个保留周期。要打破这个循环,在闭包内使用弱自我。

答案 1 :(得分:1)

保留周期是指两个对象之间具有强引用的情况。

enter image description here

您正在使用静态变量NSURLSession.sharedSession()&您可能还记得NSNotificationCenter.defaultCenter():

  

单例对象提供对资源的全局访问点   其类...您从单例类中获取全局实例   通过工厂方法。该类懒惰地创建它的唯一实例   第一次请求,然后确保没有其他   可以创建实例。单例类也会阻止调用者   复制,保留或释放实例。

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

你的“自我”实例(与其他实例一样)也没有对单例对象及其闭包的强烈引用,这就是为什么你不必担心你的保留周期。

查看这篇精彩文章了解更多详情: https://digitalleaves.com/blog/2015/05/demystifying-retain-cycles-in-arc/