强引用变量可能会导致内存问题

Aks*_*kur 14 memory-management ios automatic-ref-counting swift

我已经编程Swift了几个月了.最近,我更多地关注Swift语言如何运作的概念.


因此,最近在阅读关于自动引用计数(ARC)的Apple文档时,我遇到了以下几行:

这一个在上面:

在大多数情况下,这意味着内存管理在Swift中"正常工作",您不需要自己考虑内存管理.当不再需要这些实例时,ARC会自动释放类实例使用的内存.

在下一段中,以下内容如下:

为了实现这一点,无论何时将类实例分配给属性,常量或变量,该属性,常量或变量都会对实例进行强引用.该引用被称为"强"引用,因为它保持对该实例的坚定持有,并且只要该强引用仍然存在就不允许它被释放.


我对这种情况的动态有点困惑.我在使用故事板时注意到,你设置了对弱的引用,因此类看起来像这样,我也称之为案例1:

情况1

class SomeClass : UIViewController {
    @IBOutlet weak var nameLabel : UILabel!

    override func viewDidLoad() {
        nameLabel.text = "something."  
    }  
}
Run Code Online (Sandbox Code Playgroud)

这里,标签与ViewController有一对一的弱引用,一旦Controller被更改,引用就会被破坏(内存dealloc),因为它很弱.因此,没有与内存有关的问题.

如果上述陈述错误或松散,请原谅我.如果有人确认我的假设或反击它,我会很高兴.


我的问题是关于第二种情况,我不使用故事板和类如下所示:

案例2

class SomeClass : UIViewController {
    var nameLabel : UILabel = {

      let label = UILabel()
      label.translatesAutoresizingMaskIntoConstraints = false
      return label

    }()

    override func viewDidLoad() {
        view.addSubView(nameLabel)
        // view.addConstraints...
    }  
}
Run Code Online (Sandbox Code Playgroud)

对于上面的情况,我的假设是ViewController与标签有一对一的强引用,ViewController中的视图也有标签的强引用..如果类被更改/标签从子视图中删除..那么我认为记忆不会被解除分配.或者至少视图控制器将保持对标签的强引用(根据文档).

我通过从视图的子视图中删除标签并打印出标签来确认这一点(它给了我一个UILabel的实例,其框架为0原点和0大小.)因此一个实例不是零.

我唯一可以从中收集到的是,尽管标签已从UIView中删除,但它仍然保持与控制器的强引用,因此在内存中保持永久状态.我对吗?

如果是这样的话.我应该如何防止我的代码出现此类内存问题?更大的问题是,如果我像这样声明我的变量,我将它添加为nil,同时将其添加为控制器中主视图的子视图.

    weak var nameLabel : UILabel = {

      let label = UILabel()
      label.translatesAutoresizingMaskIntoConstraints = false
      return label

    }()
Run Code Online (Sandbox Code Playgroud)

如果在第二种情况下声明变量会导致永久强引用,那么我应该如何声明它们而不是内存问题呢?


总而言之,我的问题是:

如果没有使用故事板出口,并且变量被强烈引用到视图控制器,这些引用是否会导致内存问题?

如果是这样,我code declaration practice必须遵循什么?

如果不是这样,请提供有思想的论据和有效的解释来对抗它.


如果我在任何地方都不正确,请再次原谅我.

先感谢您.

mat*_*att 11

我唯一可以从中收集到的是,尽管标签已从UIView中删除,但它仍然保持与控制器的强引用,因此在内存中保持永久状态.我对吗?

不,这里没有大问题.

标签没有对视图控制器的强引用 - 如果是,将是一个保留周期并且会导致标签和视图控制器泄漏.出于这个原因,视图永远不应该保持对其视图控制器的强引用.

然而,这是另一种方式:视图控制器具有对标签的强引用.没关系.确实,标签在从超级视图中删除后仍然存在.但那可能并不坏.在很多情况下,这很好!例如,假设您打算稍后将标签放回界面; 你需要保留它.

如果您确定以后不需要保留标签,那么只需使用Optional包装UILabel作为您的实例属性.这样,您可以nil在完成标签实例属性时将其分配给标签实例属性,标签将不再存在.

但无论如何,这里没有泄漏,你应该停止担心.当视图控制器不存在时,标签也将不存在.这个标签的寿命比以往任何时候都要长,但这对于大规模的事情来说是微不足道的.

  • 我只是背诵了一些事实.这不是有任何怀疑或辩论的余地.如果您在掌握内存管理的工作方式时遇到困难,可以阅读本书的内存管理部分:https://apeth.com/iOSBook/ch12.html#_memory_management本章的免费在线版本是关于Objective-C的,但基本事实与Swift相同.事实上,我会详细介绍ARC在本章的这一版本中所做的事情,而不是本书的现代版本,因为正如你之前所说,ARC"只是有效"所以没有必要担心这些细节. (2认同)