【问题标题】:ARC weak var Swift (not closures)ARC 弱 var Swift(不是闭包)
【发布时间】:2017-06-23 01:55:18
【问题描述】:

我正在努力更好地理解 ARC 并正在使用 Apples Documentation

通过第一个示例,我没有得到 Apple 声明的预期结果; “因为弱引用不会对其引用的实例保持强控制,所以当弱引用仍在引用它时,该实例可能会被释放。因此,ARC 自动将弱引用设置为 nil 当实例它指的是被释放。”

我在 XCode 8.3.2 中使用游乐场

import UIKit

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { print("\(name) is being deinitialized") }
}

class Apartment {
    let unit: String
    init(unit: String) { self.unit = unit }
    weak var tenant: Person?
    deinit { print("Apartment \(unit) is being deinitialized") }
}


var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil //This prints "John Appleseed is being deinitialized" (as expected)
unit4a?.tenant?.name //This shows "John Appleseed" (expected nil)
unit4a = nil //Prints "Unit4a is being deinitialized" (as expected)

我知道这会阻止强引用循环,以便可以取消初始化两者,但我不明白为什么 unit4a 保留对租户的引用?

【问题讨论】:

    标签: swift automatic-ref-counting weak-references swift-playground


    【解决方案1】:

    您被右侧的游乐场输出所欺骗,该输出与您的打印的时间顺序不同(如在 deinits 中)。如果您将独立的“回声”替换为实际的打印调用,您将在控制台中看到,租户在您打印 unit4a?.tenant?.name 之后而不是之前被释放。这是因为弱对象的释放不会立即发生,而是在下一个运行循环中发生。 导入 UIKit 导入 XCPlayground

    XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
    
    class Person {
        let name: String
        init(name: String) { self.name = name }
        var apartment: Apartment?
        deinit { print("\(name) is being deinitialized") }
    }
    
    class Apartment {
        let unit: String
        init(unit: String) { self.unit = unit }
        weak var tenant: Person?
        deinit { print("Apartment \(unit) is being deinitialized") }
    }
    
    
    var john: Person?
    var unit4a: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4a = Apartment(unit: "4A")
    
    john!.apartment = unit4a
    unit4a!.tenant = john
    
    john = nil
    print(unit4a?.tenant?.name)
    unit4a = nil
    

    输出:

    Optional("John Appleseed")
    John Appleseed is being deinitialized
    Apartment 4A is being deinitialized
    

    但是,如果您将最后一位更改为:

    john = nil
    
    DispatchQueue.main.asyncAfter(deadline: .now()) {
        print(unit4a?.tenant?.name) //This shows "John Appleseed" (expected nil)
        unit4a = nil //Prints "Unit4a is being deinitialized" (as expected)
    }
    

    输出是你所期望的:

    John Appleseed is being deinitialized
    nil
    Apartment 4A is being deinitialized
    

    在大多数情况下,您不会关心对象是否立即释放,但如果您这样做,请检查自动释放池

    【讨论】:

      猜你喜欢
      • 2015-08-18
      • 2014-09-03
      • 2014-08-06
      • 2011-10-21
      • 2011-12-16
      • 2011-12-08
      相关资源
      最近更新 更多