2015-05-26 2 views
6

Я сейчас в порядке Apple Documentation. Вот мой вопрос:ARC (Automatic Reference Counting) in Action

class Person { 
    let name: String 
    init(name: String) { 
     self.name = name 
     println("\(name) is being initialized") 
    } 
    deinit { 
     println("\(name) is being deinitialized") 
    } 
} 

class ViewController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     var reference1: Person? 
     var reference2: Person? 
     var reference3: Person? 
     reference1 = Person(name: "John Appleseed") 
     // prints "John Appleseed is being initialized 
     reference2 = reference1 
     reference3 = reference1 

     reference1 = nil 
     reference2 = nil 
    } 
} 

После reference1 равна nil, ARC освобождает экземпляр и печатает "John Appleseed is being deinitialized"

Не должно быть после reference3 = nil освобождает?

+0

@JakubVano Чтобы получить больше информации я бегу этот код в viewDidLoad() метод. Однако reference3 не равен нулю, компилятор освобождает экземпляр, даже если существует сильная ссылка. – ridvankucuk

+0

Этот снимок экрана добавил беспорядок, а не ясность. – nhgrif

+0

Как вы определяете * точный * момент, когда происходит 'deinit'? Я ожидаю, что он будет вызван, как только метод вернется (и определенно не через мгновение). Его можно назвать раньше из-за какой-то оптимизации, но он определенно не собирается обходить после того, как метод вернется. – nhgrif

ответ

6

Проблема здесь вопрос масштаба. Мы можем узнать больше с точками останова.

Здесь мы остановлены перед инициализацией reference1.
Все переменные ожидаемо nil:

enter image description here

И после инициализации reference1?

enter image description here


Хорошо, давайте пропустим вперед после reference2 и reference3 устанавливаются:

enter image description here

Все три переменные указывают на то же место памяти, и мы можем увидеть инициализатору только один раз. Все они указывают на одно и то же место.

Давайте шаг вперед:

enter image description here

reference1 теперь указывает на None. Это nil. deinit mmethod не был вызван и не напечатал его сообщение.

Давайте шаг вперед несколько больше:

enter image description here

Теперь reference1 и reference2 оба ожидаемо nil. Были вызваны заявления , которые я добавил. Но deinit не запускался и reference3 не nil.

Следующий шаг - шаг за шагом из метода.После того, как мы из метода, переменные из области видимости и deinit называется:

enter image description here

1

Он освобождается, потому что компилятор может распознать, что больше не используется локально созданный объект. Например, в нижеприведенном коде после выполнения метода viewDidLoad метод Person будет освобожден из-за отсутствия возможности использовать объект person в будущем.

override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib.\ 

     var reference1: Person? 
     var reference2: Person? 
     var reference3: Person? 
     reference1 = Person(name: "John Appleseed") 
     // prints "John Appleseed is being initialized 
     reference2 = reference1 
     reference3 = reference1 

     reference1 = nil 
     reference2 = nil 

//  println(reference3?.name) 
} 

Если вы хотите сохранить объект, то вам нужно создать reference3, как property, как показано ниже:

class ViewController: UIViewController { 

    var reference3 : Person? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     var reference1: Person? 
     var reference2: Person? 

     reference1 = Person(name: "John Appleseed") 
     // prints "John Appleseed is being initialized 
     reference2 = reference1 
     reference3 = reference1 

     reference1 = nil 
     reference2 = nil 

//  println(reference3?.name) 
    } 

    override func viewDidAppear(animated: Bool) { 
     super.viewDidAppear(animated) 
     println(reference3?.name) 
    } 

} 
+0

Я могу получить доступ к ** reference3? .name **, даже если ** reference3 ** не является глобальным. – ridvankucuk

+0

Приложение не будет скомпилировано, если вы объявите reference3 в didLoad и используете в didAppear. – kmithi