我已经学习使用Swift
编程几个月了,最近我更关注于了解Swift
语言的工作原理。
因此,在阅读苹果公司有关自动引用计数(ARC)的文档时,我遇到了以下内容:
首先是这段文字:
在大多数情况下,这意味着在 Swift 中内存管理“只管用”,您不需要自己考虑内存管理。 ARC 会在不再需要这些实例时自动释放类实例所使用的内存。
接下来是下一段文字:
为了实现这一点,每当您将类实例分配给属性、常量或变量时,该属性、常量或变量都会对该实例进行强引用。该引用被称为“强引用”,因为它牢牢地保持着该实例,并且只要该强引用存在,就不允许将其释放。
我对这种情况的动态有些困惑。我注意到在使用故事板时,您将引用设置为弱引用,因此类看起来像这样,也就是我所说的情况1:
情况1
class SomeClass : UIViewController {
@IBOutlet weak var nameLabel : UILabel!
override func viewDidLoad() {
nameLabel.text = "something."
}
}
在这里,该标签与 ViewController 之间存在一对一的弱引用关系,只要控制器发生改变,引用就会断开(内存释放),因为它是弱引用。因此,不存在与内存相关的任何问题。
如果上述语句有误或不严谨,请原谅。如果有人能够确认我的假设或者反驳我的假设,我将不胜感激。
然而,我的问题是关于第二种情况,其中我不使用故事板,类似于以下内容:
案例2
class SomeClass : UIViewController {
var nameLabel : UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
view.addSubView(nameLabel)
// view.addConstraints...
}
}
针对以上情况,我的假设是ViewController与label之间存在一对一的强引用,而ViewController内部的view也与label保持强引用。如果更改类别/从子视图中删除标签,则我认为内存将不会被释放。或者至少视图控制器将保持对标签的强引用(根据文档)。
我通过从视图的子视图中删除标签并打印出标签来确认这一点(它给了我一个带有0原点和0大小的Frame的UILabel实例),因此是一个不为nil的实例。
我能从中收集到的唯一信息是,虽然标签已从UIView中删除,但它仍然与控制器保持强引用,因此在内存中保持永久状态。我的理解正确吗?
如果这是问题所在,我应该如何防止代码出现此类内存问题?更大的问题是如果我像这样声明变量,在将其作为主视图的子视图添加时,我将得到一个nil。
weak var nameLabel : UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
如果像第二个案例一样声明变量可能会导致永久的强引用,那么我应该如何声明它们才不会出现内存问题?
因此,我的问题是:
在没有使用任何storyboard outlet的情况下,如果将变量强烈引用到视图控制器中,这些引用会导致内存问题吗?
如果是这样,请提供代码声明实践
。
如果不是这样,请提供有力的论据和有效的解释加以反驳。
如果我有任何错误之处,请谅解。
提前感谢你。