Быстрая память Deinit во время переназначения - PullRequest
1 голос
/ 17 марта 2020

Допустим, у меня есть пользовательский класс 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 никогда не равна нулю, просто постоянно меняется?

1 Ответ

1 голос
/ 18 марта 2020

Когда вы делаете ...

var image: CIImage = MyCIImage(cvPixelBuffer: somePixelBuffer)

..., что приведет к вашему первому оператору записи «Init».

Когда вы тогда выполните ...

image = MyCIImage(cvPixelBuffer: someOtherPixelBuffer)

... это будет делать две вещи:

  1. Вы создаете новый экземпляр MyCIImage, который приводит к другому сообщению журнала «Init», связанному с этим новым экземпляром. ,

  2. Но поскольку вы заменяете свою сильную ссылку, image, на старую MyCIImage ссылкой на новую, вы удаляете свою сильную ссылку на это первый случай. А поскольку у этого первого экземпляра нет остающихся сильных ссылок, он будет освобожден, и вы увидите связанное с ним сообщение журнала «Deinit».

Вы спросили:

Почему память вообще деинициализируется, а не просто переназначается? Разве адрес памяти не останется прежним, и элемент, в котором адрес памяти просто изменится?

Нет. Когда вы создаете новый экземпляр (с синтаксисом MyCIImage(...)), он создает новый объект с новым адресом. Вот как работает подсчет ссылок и автоматов c.

Если нет, то возможен ли этот случай? Так что образ памяти @ address никогда не равен нулю, просто постоянно меняется?

Единственный способ предотвратить получение нового адреса - это если вы воздержитесь от создания нового экземпляра вашего типа (т.е. , если вы работаете только с этим оригинальным экземпляром и избегаете создания нового).

Но если это новое изображение, мы просто создаем для него новый экземпляр и не беспокоимся о том, что это новый объект. Многие из свойств (например, pixelBuffer, cgImage, et c.) Вашего родительского класса, CIImage только для чтения и не могут быть выгружены или изменилось за кадром. Ваш родительский класс CIImage действительно предназначен для одного уникального изображения. Как общий принцип проектирования, это очень хорошая вещь, позволяющая избежать многих видов проблем, которые могут возникнуть в результате непреднамеренного совместного использования. И в этом случае, именно так CIImage был разработан для работы.

...