6

Ho un metodo che si blocca di tanto in tanto.È "autonomo" debole all'interno di un metodo in ARC?

-(void)foo{ 
    [self doSomething]; 
    [self.delegate didFinish]; 
    [self doSomethingElse]; 
} 

-doSomething funziona correttamente, quindi chiamo un delegato -didFinish. All'interno di -didFinish, il riferimento a questo oggetto potrebbe essere impostato su zero, rilasciandolo sotto ARC. Quando il metodo si arresta, lo fa su -doSomethingElse. La mia ipotesi era che il sé sarebbe stato forte all'interno di un metodo, permettendo alla funzione di completarsi. È debole o forte? C'è documentazione su questo? Quale sarebbe il ragionamento per essere forte o debole?

Modifica

Dopo essere stato ispirato da alcune delle risposte di seguito, ho fatto qualche indagine. La causa effettiva del crash nel mio caso era che NSNotificationCenter non conservasse l'osservatore in ogni caso. Mike Weller indica che i chiamanti dei metodi devono conservare l'oggetto mentre viene chiamato per evitare il caso che ho descritto sopra, tuttavia sembra che NSNotificationCenter ignori questo problema e mantenga sempre un debole riferimento all'osservatore. In altre parole:

-(void)setupNotification{ 
    //observer is weakly referenced when added to NSNotificationCenter 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(handleNotification:) 
               name:SomeNotification object:nil]; 
} 

//handle the notification 
-(void)handleNotification:(id)notification{ 
    //owner has reference so this is fine 
    [self doSomething]; 
    //call back to the owner/delegate, owner sets reference to nil 
    [self.delegate didFinish]; 
    //object has been dealloc'ed, crash 
    [self doSomethingElse]; 
} 
+2

Se è '' weak' quindi self' dovrebbe diventare 'quelle negative, e l'invio di un messaggio a' quelle negative non vada in crash. Quindi indovinerei, neanche. – kennytm

+0

Hai usato 'NSLog' per vedere cosa succede con' self.delegate'? – Desdenova

+0

Dovresti pubblicare un po 'più di codice e la traccia dello stack, anche se si verificano eccezioni o errori. Come viene dichiarato il delegato? –

risposta

9

self sarebbe forte all'interno di un metodo, consentendo il completamento della funzione. È debole o forte?

self non è né forte né debole in ARC. Si presume che il chiamante abbia un riferimento e che self non sia sicuro..

È anche vero che self può essere -dealloc ed all'interno del proprio metodo in ARC, ed è considerato come "comportamento non definito (o almeno pericoloso)" per il tuo programma farlo.

Quale sarebbe il ragionamento per essere forte o debole?

E 'non trattenuti per prestazioni - per evitare ciò che è (nella stragrande maggioranza dei casi) un inutile conteggio di riferimento inc/dicembre Anche se facessero tutte quelle operazioni extra di conteggio dei ref, il tuo programma sarebbe comunque suscettibile a tali problemi nei programmi multithreaded o in presenza di una race condition (anche UB).Quindi questo è uno di quei casi estremi che (giustamente) hanno determinato di cui non hanno bisogno di difendersi.

C'è documentazione?

Of course! :)

+0

"e viene considerato come" comportamento non definito (o almeno pericoloso) "per consentire al programma di eseguire questa operazione." Stai dicendo che se accadono cose brutte nel tuo programma, allora è un comportamento indefinito. Beh, certo, ma non è utile. Come potrebbe sapere il programmatore che ciò potrebbe accadere? – newacct

+0

@newacct che è una citazione dai documenti collegati. lo scopo della dichiarazione è chiaro (anche se avrei omesso il bit "almeno pericoloso"). questo non accade per caso. sembrerebbe * per caso fino a quando il problema non verrà identificato. lo scopo della dichiarazione è: quando/se il tuo programma permette che questo accada, consideralo come un comportamento indefinito. comportamento indefinito ha una definizione molto specifica in C langs. quindi l'istruzione serve a specificare la gravità di questo errore (se rilevato). un programmatore che comprende il loro programma potrebbe identificarlo durante lo sviluppo. anche arresti anomali e zombi. – justin

+0

Un oggetto viene deallocato quando non ha più riferimenti forti. Il problema è che qualsiasi chiamata al metodo potrebbe potenzialmente causare la rimozione dell'ultimo riferimento forte all'oggetto corrente. Quindi sotto quella definizione, qualsiasi metodo che contiene una chiamata al metodo è un comportamento indefinito (a meno che non sia provato diversamente)? Ciò renderebbe il "comportamento definito" piuttosto insignificante. – newacct

4

self non è né debole né forte. Se è possibile accedere a self, si è nell'ambito di una chiamata di metodo e tale chiamata di metodo viene eseguita da qualcuno tramite un riferimento che devono possedere. self è implicito come riferimento valido fino a quando è nell'ambito di validità ed è implicito che qualsiasi gestione o proprietà della memoria viene gestita dal chiamante.

Quando si chiama un metodo attraverso un riferimento debole, ARC tratterrà l'oggetto per la durata di tale chiamata di metodo (vedere this answer). Con gli avvisi del compilatore severi abilitati, sarai effettivamente costretto a creare un riferimento forte prima di inviare qualsiasi metodo a tale riferimento.

Quindi, per definizione, se un metodo viene chiamato su un oggetto, il chiamante deve già avere la proprietà e non è necessario eseguire nulla.

Ovviamente, è possibile terminare i metodi di chiamata sugli oggetti deallocati, ma questo è il risultato di un codice chiamante non valido.

+0

"e quella chiamata di metodo viene eseguita da qualcuno tramite un riferimento che devono possedere. Self viene implicitamente considerato come un riferimento valido fintantoché è nel campo di applicazione, ed è implicito che qualsiasi gestione o proprietà della memoria è gestita dal chiamante." Tuttavia, qualcosa che fai con questo metodo potrebbe inavvertitamente interrompere la relazione di proprietà originale. È impossibile garantire in generale che 'self' punti ancora ad un oggetto valido nel mezzo del metodo. – newacct

+0

"Quindi, per definizione, se un metodo viene chiamato su un oggetto, il chiamante deve già avere la proprietà e non è necessario eseguire nulla." Non necessariamente. È garantito che il ricevitore sia valido al momento in cui inizia la chiamata; non vi è alcuna garanzia che rimanga valido per la durata della chiamata. – newacct

Problemi correlati