ARC(自动引用计数)实战

ARC(Automatic Reference Counting) in Action

我目前正在关注Apple Documentation。这是我的问题:

class Person {
    let name: String
    init(name: String) {
        self.name = name
        println("\(name) is being initialized")
    }
    deinit {
        println("\(name) is being deinitialized")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        var reference1: Person?
        var reference2: Person?
        var reference3: Person?
        reference1 = Person(name: "John Appleseed")
        // prints "John Appleseed is being initialized
        reference2 = reference1
        reference3 = reference1

        reference1 = nil
        reference2 = nil
    }
}

reference1 等于 nil 之后,ARC 释放实例并打印 "John Appleseed is being deinitialized"

不应该在reference3 = nil之后解除分配吗?

它正在释放,因为编译器能够识别不再使用本地创建的对象。例如在下面的代码中执行 viewDidLoad 方法后 Person 将被释放,因为将来没有人使用 person 对象。

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.\

        var reference1: Person?
        var reference2: Person?
        var reference3: Person?
        reference1 = Person(name: "John Appleseed")
        // prints "John Appleseed is being initialized
        reference2 = reference1
        reference3 = reference1

        reference1 = nil
        reference2 = nil

//        println(reference3?.name)
}

如果要保留对象,则需要将 reference3 创建为 property,如下所示:

class ViewController: UIViewController {

    var reference3 : Person?

    override func viewDidLoad() {
        super.viewDidLoad()

        var reference1: Person?
        var reference2: Person?

        reference1 = Person(name: "John Appleseed")
        // prints "John Appleseed is being initialized
        reference2 = reference1
        reference3 = reference1

        reference1 = nil
        reference2 = nil

//        println(reference3?.name)
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        println(reference3?.name)
    }

}

这里的问题是范围问题。我们可以通过断点来了解更多。

在这里,我们在初始化 reference1 之前停止了。
所有变量都是预期的 nil:

然后 reference1 初始化之后?


好的,让我们跳到设置 reference2reference3 之后:

所有三个变量都指向相同的内存位置,我们只能看到初始化程序 运行 一次。这些都指向同一个位置。

让我们向前走:

reference1 现在指向 None。是nildeinit mm 方法尚未被调用并打印其消息。

让我们更进一步:

现在 reference1reference2 都是预期的 nil。调用了我添加的 println 语句。但是 deinit 没有 运行 并且 reference3 不是 nil.

下一步是逐步退出方法。一旦我们离开方法,变量就超出范围并且 deinit 被调用: