2012-03-10 10 views
6

Qual è l'equivalente di [[something retain] autorelease] in ARC?Qual è l'equivalente di '[[something retain] autorelease]' in ARC?

Ho un problema in cui una classe DBRequest chiama il mio delegato per indicare il completamento. Il mio delegato quindi imposta l'istanza DBRequest su zero, che è dealloc. Ma poi quando la pila esce dal mio delegato e torna al DBRequest, ovviamente si blocca.

Se non fossi in ARC, nel mio delegato farei semplicemente il [[theDbRequest retain] autorelease] prima di rilasciare il mio riferimento ad esso, in modo che sopravviva abbastanza a lungo fino al prossimo ciclo di esecuzione.

Cosa devo fare in ARC?

risposta

6

ne dite di aggiungere qualcosa di simile

__strong DBRequest * myself = self; 
[delegate reportDone]; 

Penso che sarà incrementare l'oggetto sé fino alla fine della funzione impedendogli di morire presto.

+0

I * potrebbe * aprire il codice del dropbox e farlo ... speravo che ci sarebbe stato un modo per farlo senza bisogno di modificare il loro codice. – Chris

+3

@Chris, Ok, non mi ero reso conto che quel bit era nel loro codice. Non sono sicuro, ma potresti essere in grado di inserire un __autoreleasing DBRequest * theDBRequest = dbRequest' nel tuo codice. –

+1

Alla fine, è esattamente quello che ho fatto :) – Chris

3

Il mio delegato imposta quindi l'istanza DBRequest su zero, che è dealloc. Ma poi quando la pila esce dal mio delegato e torna al DBRequest, ovviamente si blocca.

Sicuramente questa è sempre stata una brutta strategia, e il tuo [[theDbRequest retain] autorelease] ha sempre risolto il problema, sì?

Semplicemente non fare nulla. Quindi la variabile di istanza si attacca; e allora? Sapete che ARC lo rilascerà per voi quando vi siete disfocati.

La cosa importante è di non rilasciare theDbRequest, ma per impostare il riferimento di theDbRequest per si (il delegato) a zero, in modo che non cerca di richiamare quando non esistono più. Il tuo dealloc sarebbe un buon posto per farlo.

Spero di aver compreso correttamente il problema. In caso contrario, inserisci un codice!

+0

Penso che sia un il problema causato dall'API dropbox in questione non viene scritto usando ARC, quindi in qualche modo non riesco a capire la proprietà in questione. So che ogni volta che chiami un delegato che è probabile che ti liberi, è una buona idea chiamare prima "autorelease self retain", ma l'API di dropbox non lo fa, quindi devo fare qualcosa. Ma cosa? – Chris

+0

Anche qui c'è qualcosa di interessante, se non ho impostato il parametro DbRequest su zero, non viene mai rilasciato affatto (anche dopo che il mio delegato è stato rilasciato). ARC funziona in modi misteriosi? Tentativo di tornare a terra non ad arco ... – Chris

+0

Scusa non conosco l'API DropBox. Potrebbe esserci un problema di denominazione? ARC fa delle ipotesi su come gestire la memoria in base al * nome * del metodo quando si passa da un file non ARC a un file ARC. C'è un ottimo video del WWDC 2011 che si occupa di questo; ci sono modi per aggirarlo aggiungendo un qualificatore che dice a ARC cosa fare. – matt

3

Come @ Matt dice che se semplicemente non fare nulla ARC dovrebbe pulire quando l'oggetto è deallocato - l'assegnazione del DBRequest si crea a una variabile di istanza gestisce che (fornito naturalmente il vostro oggetto sopravvive l'oggetto che si sta creando).

Se è necessario rilasciare il DBRequestprima l'oggetto muore, allora avete bisogno di un "trucco" ARC-compatibile equivalente a [[theDbRequest retain] autorelease]. Ora, a meno che non stiate costruendo i vostri pool di rilascio automatico, il vostro approccio precedente si innescherebbe alla fine dell'evento corrente. Seguendo questa logica prova:

  1. aggiungere un metodo alla classe che definisce semplicemente theDbRequest-nil, chiamiamolo questo cleanUpTheDbRequest.
  2. Cambia il callback delegato per invocare [self performSelectorOnMainThread:@selector(cleanUpTheDbRequest) withObject:nil waitUntilDone:NO] invece di assegnare direttamente nil a theDbRequest

Questo dovrebbe ritardare l'assegnazione di nil fino a dopo la fine della manifestazione in corso, proprio come il tuo autorelease "trucco" ha fatto.Funziona anche se il tuo DBRequest sopravvive su più eventi - il metodo precedente viene attivato alla fine dell'evento, viene chiamato il autorelease, questo metodo alla fine dell'evento viene chiamato il metodo delegato.

Problemi correlati