【问题标题】:Reference count in ARCARC 中的引用计数
【发布时间】:2017-04-09 12:19:44
【问题描述】:

我对@9​​87654321@ 的引用计数有点困惑,你能告诉我下面代码的引用计数是多少。

var vc1 = UIViewController()
var vc2 = vc1
var vc3 = vc2
weak var vc4 = vc3

问题是:

  • vc1 的引用计数?
  • vc2 的引用计数?
  • vc3 的引用计数?
  • vc4 的引用计数?

【问题讨论】:

    标签: ios objective-c swift automatic-ref-counting


    【解决方案1】:

    这里,vc1vc2vc3 指的是同一个对象。所以,那个对象的引用计数是3。当vc4引用同一个对象时,由于是弱引用,所以引用计数不会加1。所以,这之后的引用计数也会是3

    1. 第一行代码后vc1创建并引用的UIViewController对象的引用计数为1。

      var vc1:UIViewController? = UIViewController() // strong reference 
      
    2. vc2 之后与vc1 引用相同的对象。对象的引用计数变为2

      var vc2:UIViewController? = vc1 // strong reference
      
    3. vc3 之后与vc1vc2 引用相同的对象。对象的引用计数变为3

      var vc3:UIViewController? = vc2 // strong reference
      
    4. vc4 之后与vc1vc2vc3 引用相同的对象。由于vc4 是弱引用,所以引用计数不会增加。这意味着计数仍然是 3。

      weak var vc4:UIViewController? = vc3 // weak reference
      

    含义:

    执行以下代码。

       vc1 = nil; // reference count = 3-1 = 2
       vc2 = nil; // reference count = 2-1 = 1
       vc3 = nil; // reference count = 1-1 = 0 and object is destroyed
    

    现在,打印vc4 的值。它将是nil。发生这种情况是因为对象的引用计数变为零并且所有变量都引用了同一个对象。

    编辑:

    在下面的代码中使用CFGetRetainCount 会得到如下结果:

    var vc1:NSDate? = NSDate()
    print(CFGetRetainCount(vc1)) // 2 - I expected this to be 1 as only one variable is strongly referring this object. 
    
    var vc2:NSDate? = vc1
    print(CFGetRetainCount(vc1)) // 3 - reference count incremented by 1 (strong reference)
    
    var vc3:NSDate? = vc2
    print(CFGetRetainCount(vc3)) // 4 - reference count incremented by 1 (strong reference)
    
    weak var vc4:NSDate? = vc1
    print(CFGetRetainCount(vc1)) // 4 - reference count not incremented (weak reference)
    
    vc1 = nil
    print(CFGetRetainCount(vc2)) // 3 - reference count decremented by 1 (strong reference removed)
    
    vc2 = nil
    print(CFGetRetainCount(vc3)) // 2 - reference count decremented by 1 (strong reference removed)
    
    vc3 = nil 
    print(vc4) // nil - reference count should be decremented by 1 (last strong reference removed)
    
    // Also due to the final line vc3 = nil, reference count should become zero
    // However, we can't use `CFGetRetainCount` to get reference count in this case
    // This is due to the final strong reference being removed and object getting destroyed
    

    CFRetainCount 在第一行给出 2 的原因已经讨论过here。感谢@CodaFi 和@Sahil 在 cmets 中的讨论

    【讨论】:

    • 为什么 CFGetRetainCount 给 4 然后@KrishnaCA?
    • @Sahil CFGetRetainCount 返回 4,因为 @KrishnaCA 误解了变量赋值相对于引用计数的意图。在这个例子中,引用计数的增加并不是因为它们本身的赋值,而是因为前三个赋值是针对一个强引用。对弱引用的赋值仍然执行引用计数的临时递增(特别是,它调用_swift_weakInit)。这是所有实现定义的。你不应该考虑它:)
    • @KrishnaCA 当然。看看HeapObject.cpp,看看我们可以为这些东西发出的调用集。临时增量是一个实现细节,如果优化器可以保证每个引用的生命周期,则可以将其展平。
    • 即使您(首先更改类型,然后)将它们设置为 nil,ARC 的语义是这样的,我们不必通过递减来尊重它们。再次,它的发生是实现定义的! ARC 非常有趣,因为我们不必随身携带 ObjC 调用约定所需的所有笨重的包袱。
    【解决方案2】:

    您可以使用CFGetRetainCount 函数来检查引用计数。

    var vc1 = UIViewController()
    var vc2 = vc1
    var vc3 = vc2
    weak var vc4 = vc3
    
    
    print(CFGetRetainCount(vc1)) //4
    print(CFGetRetainCount(vc2)) //4 
    print(CFGetRetainCount(vc3)) //4
    print(CFGetRetainCount(vc4)) //4
    

    你也可以参考这个Get Ref Count

    【讨论】:

    • CFGrtRetainCount 确实返回 4 但您没有回答所询问的内容。看看 CodaFi 的 cmets 看看为什么你的答案不正确
    • @Sahil,尝试在此处获取每个步骤的保留计数并检查结果。我刚试过。如果vc1var vc1 = UIViewController() 之后的保留计数为2。请确认
    【解决方案3】:

    在我看来,从 vc1 到 vc3 会增加保留计数,默认属性是 strong,直到我们将它们指定为 weak

    strong: 类通常使用Strong来建立对象的所有权。它增加了保留计数(ARC 为您处理的事情),它基本上将指向的对象保留在内存中,直到该类实例停止指向它。这通常是你想要的,但它可能会导致所谓的“保留周期”。

    如果是 vc4,你定义为weak

    弱: 这会给出一个指向对象的指针,但不会声明所有权,也不会增加保留计数。只要另一个类强烈指向它,它基本上就会保留一个指向对象的有效指针。如果没有其他东西试图保留它,弱指针会自动设置为 nil。

    【讨论】:

      【解决方案4】:

      1,2,3,4 - 引用计数为 3

      引用计数不会增加的唯一例外 - 第 4 行,因为修改器较弱

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-21
        • 2012-03-13
        • 1970-01-01
        • 1970-01-01
        • 2012-01-11
        • 1970-01-01
        • 2015-09-29
        相关资源
        最近更新 更多