Swift: некоторые классы не деинициализированы - PullRequest
0 голосов
/ 22 апреля 2019

В следующем коде NSString и NSNumber не деинициализируются при удалении ссылки. NSMutableString и NSAttributedString деинициализированы. Каковы критерии для deinit?

class WeakHolder<R : AnyObject> {
    weak var cheez : R?
    init(_ _cheez : R) {
        cheez = _cheez
    }
}

do {
        var nsStringCollection = [NSString(string: "77"),NSString(string: "99")]
        let weakNSStringHolder = WeakHolder(nsStringCollection[1])
        nsStringCollection.removeLast()
        print("NSString : \(weakNSStringHolder.cheez)")
    }

    do {
        var nsMutableStringCollection = [NSMutableString(string: "77_m"),NSMutableString(string: "99_m")]
        let weakNSMutableStringHolder = WeakHolder(nsMutableStringCollection[1])
        nsMutableStringCollection.removeLast()
        print("NSMutableString : \(weakNSMutableStringHolder.cheez)")
    }

    do {
        var nsNumberCollection = [NSNumber(integerLiteral: 77),NSNumber(integerLiteral: 99)]
        let weakNumberHolder = WeakHolder(nsNumberCollection[1])
        nsNumberCollection.removeLast()
        print("Number : \(weakNumberHolder.cheez)")
    }

    do {
        var nsAttributedCollection = [NSAttributedString(string: "77_atts"),NSAttributedString(string: "99_atts")]
        let weakAttributedHolder = WeakHolder(nsAttributedCollection[1])
        nsAttributedCollection.removeLast()
        print("AttrString : \(weakAttributedHolder.cheez)")
    }

Выход:

NSString : Optional(99)
NSMutableString : nil
Number : Optional(99)
AttrString : nil

1 Ответ

1 голос
/ 22 апреля 2019

Short NSString объекты хранятся непосредственно в своем (тегированном) указателе и не требуют управления памятью. Другие статические строки хранятся в двоичном файле и никогда не могут быть освобождены. Не выделяйте память, поэтому не должны освобождать ее.

NSMutableString и NSAttributedString выделяют фактические объекты, поэтому они также должны освобождать их.

Оба поведения являются деталями реализации, и вы не должны полагаться на них. Они не обещаны.

Правило для управления памятью - строгое указание на все, что вам небезразлично, и устраняйте строгое указание, когда оно вам больше не нужно. deinit должен очищать только память (например, при вызове free для блоков malloc). Никакая «бизнес-логика» не должна быть в deinit; нет никакого обещания, что это когда-либо будет бежать. (Например, при обычном завершении программы deinit пропускается, в отличие от C ++.)

...