Swift 重新分配期间内存取消初始化

Swift Memory Deinit During Reassignment

假设我有一个自定义 CIImage class。

import UIKit

class MyCIImage: CIImage {

    var VC:RealtimeDepthMaskViewController!

    deinit { print("Deinit") }

    override init(cvPixelBuffer pixelBuffer: CVPixelBuffer) {
        super.init(cvPixelBuffer: pixelBuffer)
    }

    override init(cvPixelBuffer pixelBuffer: CVPixelBuffer, options: [CIImageOption : Any]? = nil) {
        super.init(cvPixelBuffer: pixelBuffer, options: options)
    }

    convenience init(cvPixelBuffer pixelBuffer: CVPixelBuffer, VC:RealtimeDepthMaskViewController) {
        self.init(cvPixelBuffer: pixelBuffer)
        self.VC = VC
        print("Init")
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

然后我们创建并分配一个变量。

let image:CIImage = MyCIImage(cvPixelBuffer: somePixelBuffer) //"Init"

然后,我想重新分配变量

image = MyCIImage(cvPixelBuffer: someOtherPixelBuffer) //"Init" "Deinit"

执行这 2 个命令得到的打印输出是

"Init"
"Init"
"Deinit"

为什么内存完全被取消初始化而不只是重新分配?内存地址不会保持不变,而内存地址所在的项目不会改变吗?如果不是,这是可能的情况吗?这样内存@地址image永远不会为零,只是不断变化?

当你做...

var image: CIImage = MyCIImage(cvPixelBuffer: somePixelBuffer)

...这将导致您的第一个“Init”日志记录语句。

然后当你做...

image = MyCIImage(cvPixelBuffer: someOtherPixelBuffer)

...这将做两件事:

  1. 您正在创建一个新的 MyCIImage 实例,这会导致另一个与此新实例关联的“Init”日志消息。

  2. 但是,因为您要用新的引用替换旧的 MyCIImage 的强引用 image,所以您要删除强引用参考第一个实例。而且,因为第一个实例没有剩余的强引用,它将被释放,您将看到与之关联的“Deinit”日志消息。

您问的是:

Why is the memory getting deinitialized at all and not just reassigned? Wouldn't the memory address stay the same and the item at which the memory address is just change?

没有。当您创建一个新实例(使用 MyCIImage(...) 语法)时,它会创建一个具有新地址的新 object。这就是 objects 和自动引用计数的工作原理。

If not, is this a possible case? So that the memory @ address image is never nil, just constantly changing?

阻止它获得新地址的唯一方法是避免创建您的类型的新实例(即,如果您只使用该原始实例并避免创建新实例)。

但是如果它是一个新的图像,我们只是为它创建一个新的实例而不用担心它是一个新的 object。您的 parent、class、CIImage 的许多属性(例如 pixelBuffer, cgImage 等)都是 read-only,无法在幕后换出或更改.您的 parent class、CIImage 确实适用于单一、独特的图像。作为一般设计原则,这是一件非常好的事情,减少了无意共享可能引起的多种问题。在这种情况下,这就是 CIImage 设计的工作方式。