Swift 在重新分配过程中快速内存解隐

Swift 在重新分配过程中快速内存解隐,swift,memory,automatic-ref-counting,ciimage,Swift,Memory,Automatic Ref Counting,Ciimage,假设我有一个自定义的CIImage类 import UIKit class MyCIImage: CIImage { var VC:RealtimeDepthMaskViewController! deinit { print("Deinit") } override init(cvPixelBuffer pixelBuffer: CVPixelBuffer) { super.init(cvPixelBuffer: pixelBuffer)

假设我有一个自定义的
CIImage

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"
我从这两个命令中得到的打印输出是

"Init"
"Init"
"Deinit"
为什么记忆完全被去初始化,而不仅仅是重新分配?难道内存地址不会保持不变,而内存地址所在的项不会改变吗?如果没有,这是否可能?因此,内存@address
image
永远不会为零,只是在不断地变化?

当您这样做时

var image: CIImage = MyCIImage(cvPixelBuffer: somePixelBuffer)
。。。这将导致您的第一个“Init”日志语句

当你这样做的时候

image = MyCIImage(cvPixelBuffer: someOtherPixelBuffer)
。。。这将做两件事:

  • 您正在创建一个新的
    MyCIImage
    实例,该实例将产生另一条与此新实例关联的“Init”日志消息

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

  • 你问:

    为什么记忆完全被去初始化,而不仅仅是重新分配?难道内存地址不会保持不变,而内存地址所在的项不会改变吗

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

    如果没有,这是否可能?所以内存@地址映像永远不会为零,只是不断变化

    防止其获得新地址的唯一方法是避免创建类型的新实例(即,仅使用原始实例,避免创建新实例)


    但是如果它是一个新的图像,我们只需要为它创建一个新的实例,而不用担心它是一个新的对象。父类CIImage的许多属性(例如,等)是只读的,不能在后台调出或更改。您的父类--
    CIImage
    ,实际上是为一个唯一的映像而设计的。作为一个通用的设计原则,这是一件非常好的事情,可以减少由于无意共享而可能产生的各种问题。在本例中,这就是
    CIImage
    的工作原理。

    每次初始化类时,都会分配新内存。如果要重用具有不同数据的对象,必须在不调用init(..)的情况下分配映像。我将玩弄这些信息。首先,我假设它是
    var image=…
    ,而不是
    let
    (因为不能替换常量
    let
    引用)。其次,假设它是
    var
    ,您已经用一个新实例替换了
    image
    引用的对象,从而放弃了对前一个实例的引用(因此第一个实例的
    deinit
    ),这与此无关,但图像对
    realtimedpthmaskviewcontroller
    的引用令人担忧。图像对象不必保留对视图控制器的引用。如果这真的是您试图实现的委托模式,您通常会使用协议(使它们松散耦合)并使引用变弱(避免强引用循环).哎哟-那是为了测试保留周期,并尝试确定为什么它会出现在内存中,如果有对VC的强烈引用。我理解这是一种糟糕的模式——更多的是一种研究。它不是为了实际目的而存在的。这是一个var,我写了测试,我得出了这个结论。现在的目标是如何恰当地进行我的设计模式以实现我的目标。谢谢