【问题标题】:Why doesn't my instance get deallocated?为什么我的实例没有被释放?
【发布时间】:2023-03-28 09:04:01
【问题描述】:

我有一个 Person 类如下:

class Person{
    var name: String?

    init(name: String){
        self.name = name
    }
    func doWithDelay(){
        let when = DispatchTime.now() + 2
        DispatchQueue.main.asyncAfter(deadline: when) { [weak self] in
            self?.name = "delayed"

            print(self?.name )
        }
    }
    deinit {
        print("Person class is deinited \(self)")
    }
}

我在下面的 viewController 中创建了一个Person 的实例:

class ViewController: UIViewController {
    var p1 :Person? = Person(name: "MMM")

    override func viewDidLoad() {
        super.viewDidLoad()

        var persons : [Person] = []

        p1!.doWithDelay()

        persons.append(p1!)


        var p3 = Person(name: "OOO") // AAA

        persons.removeAll()

    }

}

如果我有var p3 = Person(name: "OOO"),那么我的p1 实例 被释放,但是如果我注释掉AAA 行或简单地用var p3 = "howareyou" 替换它,那么我的实例Person 实例根本不会被释放。

为什么?!

【问题讨论】:

  • 行为的哪一部分令人惊讶?如果您有var p3 = Person,则该人将被解除分配。如果你不这样做,就没有什么可以释放的了。在任何一种情况下,您的实例 var p1 都不会在控制器释放之前被释放,因为控制器正在持有它。
  • 回应您最近的编辑:不,您的 p1 实例没有被释放。 p3 是,因为它是一个局部变量。尝试打印deinit 中的人名。
  • @ConnorNeville ????谢谢。是的,我在想p1 正在被释放。还有一个问题。我刚刚将p3 附加到persons,但它仍然被释放。 persons 不是应该坚持p3 吗?我已经阅读了所有关于ARC...据我了解的是:persons 将增加p3 的保留计数,但不确定之后会发生什么。
  • @Honey persons 也是一个局部变量,因此将在方法范围的末尾取消初始化,因此减少其所有元素的保留计数,从而允许您的 p3 实例被释放。

标签: swift memory-management


【解决方案1】:

问题是你无法区分一个人和另一个人。像这样重写你的 Person 类:

class Person: NSObject{
    var name: String?

    init(name: String){
        self.name = name
        super.init()
        NSLog("%@", "Person class is inited \(self)")
    }
    func doWithDelay(){
        let when = DispatchTime.now() + 2
        DispatchQueue.main.asyncAfter(deadline: when) { [weak self] in
            self?.name = "delayed"

            print(self?.name )
        }
    }
    deinit {
        NSLog("%@", "Person class is deinited \(self)")
    }
}

这里的区别是(1)我们在initdealloc 期间记录,以及(2)我们从NSObject 派生,因为它为我们提供了self 的唯一标识符,即它的内存地址。然后我们得到:

Person class is inited
<MyApp.Person: 0x618000047470> 
Person class is inited 
<MyApp.Person: 0x61000004b040> 
Person class is deinited 
<MyApp.Person: 0x61000004b040>

这正是我们期望看到的:实例属性 Person 仍然存在,但局部变量 Property 被创建并立即再次销毁。局部变量是自动的:一旦我们到达其作用域的末尾(包含花括号),它们就会被释放,因此局部变量引用的对象消失,除非您安排了更长的时间-lived 引用以保留它。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-10
  • 2011-02-15
相关资源
最近更新 更多