[英]Why doesn't referencing outside of a function create retain cycle?
抱歉,但是我知道这是一个非常愚蠢的问题,我已经有点“知道”答案了,但是我需要有人清楚地向我解释为什么答案是它的意思。
最近,在经历了各种内存问题的噩梦调试之后,我对代码的保留周期和内存泄漏有些迷恋/偏执,所以将来我希望将它们扼杀在萌芽状态。 但是,在阅读和学习了很多有关ARC的知识并保留了Swift的周期之后,尽管这很有意义,但我仍然没有足够的“直觉”或自然的感觉,以至于我有信心找到一个或一个我正在编码中缺少一个。 因此,我开始变得有点偏执,因为我甚至没有意识到就创建了包含基本内容的保留周期。
因此,考虑到这一点,为什么任何使用在其外部声明的变量的普通函数都不会创建保留周期? 例如:
class someClass {
let a = "I'm letter a"
let moreLetters = addLetters()
func addLetters () -> String {
let newString = a + "bcdefg"
return newString
}
}
在这种情况下,self.moreLetters引用函数addLetters,然后常量self.a是函数addLetters中的引用。 如果我不捕捉弱者/无主者,那么这会形成一个保留周期吗? 在我看来,这种简单的事情会引起问题是荒谬的……还是吗? 像这样的嵌套函数呢?
func someFunction () -> String {
let a = "I'm letter a"
func addLetters () -> String {
let newString = a + "bcdefg"
return newString
}
let moreLetters = addLetters()
return moreLetters
}
这还会造成保留周期吗? (是的,我知道这是执行简单任务的复杂方法;我只是以这段代码为例来说明我的观点)。
我是否变得超级偏执狂,并且对事情认真思考?
首先,您需要了解如何形成基本的保留周期。 当对象A同时强烈引用对象B时,会形成一个保留周期。 对象B也强烈指对象A。
让我们看看您的第一段代码。
class someClass {
let a = "I'm letter a"
let moreLetters = addLetters()
func addLetters () -> String {
let newString = a + "bcdefg"
return newString
}
}
实际上,类本身永远不会创建保留周期,因此让我们添加一些代码来创建对象:
var obj = someClass()
首先,将a
初始化为“我是字母a”。 在此之后, moreLetters
通过调用该方法初始化addLetters
。 方法返回后, moreLetters
初始化为“ I'm letter abcdefg”。 到现在为止还挺好。
现在我们将obj
设置为nil
:
obj = nil
如果形成了保留循环,则不会取消初始化obj
。 但是,实际上, obj
被取消了初始化,因为没有什么东西可以强烈引用obj
!
“等一下!” 您会说:“但是方法addLetters
仍然引用someClass
因为其中包含a
!” 好吧,事实上, addLetters
已经回来了! 因此,其中的所有内容都不再重要! 另外, addLetters
属于obj
,您已经将其设置为nil
!
现在,让我们看一下您的第二个代码:
func someFunction () -> String {
let a = "I'm letter a"
func addLetters () -> String {
let newString = a + "bcdefg"
return newString
}
let moreLetters = addLetters()
return moreLetters
}
保留循环不会形成,因为甚至没有引用类型! 没有要创建的对象。 您在第二个代码中所做的全部工作就是使用字符串(它们是值类型)。 即使有一个类,也不会形成保留周期,因为正如我所说,当将obj
设置为nil
,其中的所有方法都会“消失”,因为方法属于对象。
那些必须写[weak self]
或保留周期表格的闭包呢?
这些闭包正在逃避闭包 。 普通闭包在返回后会被取消初始化。 但是,转义的闭包由某些对象保留,因此它们不会立即取消初始化。 有关更多信息,请参见在Swift中转义闭包
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.