6

Sto scrivendo codice destinato a funzionare sia in ARC che in Garbage Collection.Ponticello ARC/GC e Core Foundation dual mode

Ecco un po 'di codice che utilizza Nucleo Fondazione come potrebbe essere scritto appositamente per ARC:

CFTypeRef ref=CFCopySomething(); 
// At this point ref has retain count 1. 
id obj=(__bridge_transfer id)ref; 
// Ref still has retain count 1 but is now managed by ARC. 
[obj doSomething]; 
// ARC will release ref when done. 

Sembra che questo è equivalente a:

CFTypeRef ref=CFCopySomething(); 
// At this point ref has retain count 1. 
id obj=(__bridge id)ref; 
// Now ref has retain count 2 due to assigning to strong variable under ARC. 
CFRelease(ref) 
// Now ref has retain count 1. 
[obj doSomething]; 
// ARC will release ref when done. 

Il vantaggio di queste ultime essere che la chiamata CFRelease consente al GC di raccogliere l'oggetto. Ma non sono sicuro di chiamare il CFRelease dopo il trasferimento ad ARC con l'assegnazione cast-bridge.

Certamente sembra funzionare. Questo codice è OK?

+1

Vale la pena ricordare ai lettori che i cast di '__bridge' non hanno alcun significato su unità di compilazione non ARC, cioè il compilatore semplicemente li ignorerà durante la compilazione con' --objc-gc', rendendo compatibile il secondo snippet di codice con sia ARC che GC. (Sto solo dicendo che ho dovuto cercare.) – paulotorrens

risposta

2

Il secondo frammento di codice è corretto, e in effetti è il modo migliore per gestire sia ARC e GC. Si potrebbe anche usare CFMakeCollectable quando si crea l'oggetto, e quindi avere la CFRelease fatto come segue:

if ([NSGarbageCollector defaultCollector] == null) CFRelease (myCFString)

Ma mi piace di più quello che hai con solo una chiamata che funziona per entrambi gli ambienti.

1

Nick,

quanto CFObjects non sono gestite da ARC, si può effettivamente desidera mantenere il codice gestito manualmente qui. ARC è davvero focalizzato su Cocoa e non su Core Foundation. Detto questo, hai detto che il codice funziona ma perde? Ricordare che il codice ARC con i flag del compilatore errati non riesce a filtrare. In questa documentazione Apple, affermano che ARC non gestisce gli oggetti CF: https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html. Quindi, penso che il tuo codice __bridge rimanga e attenda la tua conferma o il tuo rifiuto dallo strumento di leak di Instruments.

Andrew

+1

Posso confermare che il codice non perde quando compilato sotto ARC. –

+0

Nick, OK, sono contento che tu l'abbia confermato. Alla domanda GC, dato che il tuo CFRelease può verificarsi ovunque dopo l'ultimo utilizzo, perché lo stai mettendo prima del tuo ultimo utilizzo e sperando che ARC/GC lo risolva? Se ti limiti a seguire il modello standard per gli oggetti CF, non devi pensare ai problemi di ARC v GC. IOW, nel secondo blocco, sposta CFRelease sull'ultimo punto in cui è necessario l'elemento. Né ARC né GC saranno molto più intelligenti di te. (BTW, penso che il tuo compito di collegamento non faccia altro che cambiare il nome. Nessuna semantica di allocazione è cambiata.) Andrew – adonoho

+1

Sotto il GC, CFRelease è necessario per contrassegnare un oggetto CF come oggetto da collezione. È normale farlo al momento della creazione (spesso usando CF/NSMakeCollectable, ma CFRelease funziona altrettanto bene). Allo stesso modo, con ARC voglio consegnare l'oggetto ad ARC il prima possibile. Funziona davvero tutto. –