Подтвердить что ты не робот

Знаете, когда слабый var становится ничтожным в Свифте?

Скажем, у меня есть weak var view: UIView? в моем class Button {}. Есть ли способ узнать, когда view теряет свою ссылку и становится nil?

Я попытался использовать weak var view: UIView? {} (иначе вычисленное свойство), чтобы переопределить set {}, но это не сработало, потому что теперь оно вычисленное свойство и не может хранить слабую ссылку (как раздражает!).

Edit:

@fqdn ответ не работал с этим кодом... Попробуйте его на игровой площадке Xcode

import UIKit

class Test {
  weak var target: UIView? {
    willSet {
      if !newValue { println("target set to nil") }
      else { println("target set to view") }
    }
  }
}

class Button {
  var view: UIView? = UIView()
}

var t = Test()
var b = Button()
t.target = b.view
b.view = nil // t.target willSet should be fired here

Ваша консоль вывода должна отображать:

target set to view
target set to nil

Моя консоль отображает

target set to view

b.view является сильной ссылкой для экземпляра UIView. t.target является слабым эталоном. Поэтому, если b.view установлен в nil, экземпляр UIView освобождается и t.target будет равен nil.

4b9b3361

Ответ 1

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

В частности, наблюдатели свойств Swift не вызывают, когда слабые ссылки становятся равными нулю, как показывает следующий код:

class A : CustomStringConvertible {
    var s: String?

    init(s: String) {
        self.s = s;
        print("\(self) init")
    }

    deinit {
        print("\(self) deinit")
    }

    var description: String {
        get { return "[A s:\(s ?? "nil")]" }
    }
}

class B : CustomStringConvertible {
    weak var a:A? {
        willSet {
            print("\(self) willSet a")
        }
        didSet {
            print("\(self) didSet a")
        }
    }

    init(a: A?) {
        self.a = a
        print("\(self) init")
    }

    deinit {
        print("\(self) deinit")
    }

    var description: String {
        get { return "[B a:\(a == nil ? "nil" : String(describing: a!))]" }
    }
}

func work() {
    var a: A? = A(s: "Hello")
    var b = B(a: a)
    print("\(b)")
    a = nil
    print("\(b)")
    b.a = A(s: "Goodbye")
}

work()

Когда вызывается work(), консоль дает следующий вывод:

[A s:Hello] init
[B a:[A s:Hello]] init
[B a:[A s:Hello]]
[A s:Hello] deinit
[B a:nil]
[A s:Goodbye] init
[B a:nil] willSet a
[B a:[A s:Goodbye]] didSet a
[A s:Goodbye] deinit
[B a:nil] deinit

Обратите внимание, что ни в случае, когда экземпляр A deallocating, а его слабая ссылка в случае B, становящегося nil, являются вызывающими свойствами наблюдателями. Только в прямом случае присвоения B.a они называются.