gpt4 book ai didi

ios - 为什么在函数外部引用不创建保留循环?

转载 作者:搜寻专家 更新时间:2023-11-01 07:17:21 26 4
gpt4 key购买 nike

抱歉,但我知道这是一个非常愚蠢的问题,我已经有点“知道”答案了,但我需要有人向我清楚地解释为什么答案是这样。

最近,我对我的代码中的循环保留和内存泄漏有点着迷/偏执,在经历了一些带有各种内存问题的噩梦般的调试之后,所以将来我想把它们消灭在萌芽状态。但是在阅读和学习了很多关于 Swift 中的 ARC 和保留循环的知识之后,尽管它是有道理的,但我对它仍然没有足够的“直觉”或自然感觉,无法自信地发现一个,或者缺少一个,因为我正在编码。所以我开始变得有点偏执,我在没有意识到的情况下甚至用基本的东西创建了保留周期。

那么,考虑到这一点,为什么任何使用在其外部声明的变量的普通函数都不会创建一个保留循环?例如:

    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 中的引用。那么如果我不捕获弱/无主 self ,这会创建一个保留周期吗?在我看来,这么简单的事情会导致问题,这似乎很荒谬……或者是这样吗?在嵌套函数中怎么样,像这样:

    func someFunction () -> String {
let a = "I'm letter a"
func addLetters () -> String {
let newString = a + "bcdefg"
return newString
}
let moreLetters = addLetters()
return moreLetters
}

这也会创建一个保留周期吗? (是的,我知道这是执行简单任务的一种复杂方式;我只是以这段代码为例来说明我的观点)。

我是不是变得 super 偏执,对事情想得太多了?

最佳答案

首先,您需要了解基本的保留循环是如何形成的。当一个对象A同时强引用一个对象B时,就会形成一个retain cycle。对象 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”。之后,通过调用方法addLetters 来初始化moreLetters。方法返回后,moreLetters 被初始化为“我是字母 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] 或保留循环形式的闭包呢?

这些闭包是转义闭包。正常的闭包在返回后被取消初始化。但是,转义闭包会被某些对象保留,因此不会立即取消初始化。有关详细信息,请参阅 Escaping Closures in Swift

关于ios - 为什么在函数外部引用不创建保留循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41414179/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com