2016-01-05 8 views
2

Вот мой код:Быстрая делегация - когда использовать слабую ссылку, почему «делегат» - это нуль?

protocol Delegate: NSObjectProtocol {} 

class A: NSObject { 
    weak var delegate: Delegate! 
    override init() { 
     super.init() 
    } 
    func start() { 
     //synchronous------- print A: false 
     print("A:", delegate == nil) 

     //asynchronous------- print B: true Why is 'true'? How can do that not be released? 
     let time: NSTimeInterval = 1 
     let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(time * Double(NSEC_PER_SEC))) 
     dispatch_after(delay, dispatch_get_main_queue()) { 
      print("B:", self.delegate == nil) 
     } 
    } 
} 

class B: NSObject, Delegate { 
    override init() { 
     super.init() 
     let a = A() 
     a.delegate = self 
     a.start() 
    } 
} 

я искал другие вопросы на переполнение стека, но я не могу найти что-то, что может помочь мне, чтобы полностью понять эту ситуацию.

+3

Посмотрите на это: http://stackoverflow.com/questions/34608397/why-is-the-uitabbarcontrollerdelegate-nil-right-after-i-set-it/34608887, возможно, это аналогичный случай. – courteouselk

ответ

2

В классе A вы определили делегата как слабый. Это означает, что если ни один другой объект не ссылается на объект делегата (экземпляр класса B в вашем случае), то этот экземпляр может быть выпущен.

В начале запуска экземпляр класса B ссылался на некоторый объект. В этом классе B вы создали экземпляр класса A и назначили экземпляр класса B в качестве его делегата. Когда вы напечатали значение делегата, это было не ноль.

Позже экземпляр класса B больше не ссылался на другой объект, помимо экземпляра класса A. Поскольку экземпляр класса А называл его слабым, его ссылка не подсчитывалась, и экземпляр A был освобожден из памяти. Вот почему, когда вы напечатали значение делегата через секунду, оно было равно нулю.

Почему использовать слабый? Если вы не использовали слабый, то экземпляр класса A будет содержать ссылку на экземпляр класса B, а экземпляр класса B будет содержать ссылку на экземпляр класса A. Таким образом, подсчет ссылок обоих экземпляров будет больше 0, и ни один из них не может быть освобожден !!! Это приведет к утечке памяти. Вы хотите, чтобы, если ни один другой объект не ссылается на объект класса B, он будет освобожден из памяти, и, следовательно, объект класса А также может быть выпущен.