2015-05-26 6 views
6

Attualmente sto seguendo lo Apple Documentation. Ecco la mia domanda:ARC (conteggio di riferimento automatico) nell'azione

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 
    } 
} 

Dopo reference1 uguale nil, ARC rilascia l'istanza e stampe "John Appleseed is being deinitialized"

non dovrebbe essere rilascia dopo reference3 = nil?

+0

@JakubVano per avere maggiori informazioni sto facendo funzionare questo codice in viewDidLoad metodo(). Comunque reference3 non è nil, il compilatore rilascia l'istanza anche se esiste il riferimento Strong. – ridvankucuk

+0

Questo screenshot ha aggiunto clutter, non chiarezza. – nhgrif

+0

Come si determina il * momento * esatto in cui si verifica il 'deinit'? Mi aspetterei che venga chiamato non appena il metodo ritorna (e sicuramente non un momento dopo). Potrebbe essere chiamato in precedenza a causa di un qualche tipo di ottimizzazione, ma sicuramente non andrà in giro dopo il ritorno del metodo. – nhgrif

risposta

6

Il problema qui è una questione di portata. Possiamo scoprire di più con i breakpoint.

Qui, ci fermiamo poco prima dell'inizializzazione di reference1.
Tutte le variabili sono da aspettarsi nil:

enter image description here

E dopo l'inizializzazione di reference1?

enter image description here


Ok, saltiamo in avanti per dopo reference2 e reference3 sono impostati:

enter image description here

Tutte e tre le variabili puntano alla stessa posizione di memoria, e possiamo vedere l'inizializzatore solo una volta. Questi puntano tutti alla stessa posizione. passo

Let avanti:

enter image description here

reference1 è ora punta a None. È nil. Il metodo deinit mm non è stato chiamato e stampato il suo messaggio. passo

Let avanti ancora un po ':

enter image description here

Ora reference1 e reference2 sono entrambi expectedly nil. Sono state chiamate le affermazioni println che ho aggiunto. Ma deinit non è stato eseguito e reference3 non è nil.

Il passaggio successivo è di uscire completamente dal metodo.Una volta che siamo fuori del metodo, le variabili sono fuori portata e l'deinit si chiama:

enter image description here

1

È deallocazione in quanto il compilatore è in grado di riconoscere che non esiste più l'uso di oggetti creati localmente. Ad esempio nel seguente codice dopo l'esecuzione del metodo viewDidLoad, il metodo Person verrà deallocato perché in futuro non è possibile utilizzare l'oggetto persona.

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) 
} 

Se si desidera mantenere l'oggetto, allora è necessario creare reference3 come property come di seguito:

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

Posso accedere a ** reference3? .name ** anche se ** reference3 ** non è globale. – ridvankucuk

+0

Nessuna app verrà compilata se stai dichiarando reference3 in didLoad e utilizzando in didAppear. – kmithi