2011-12-21 11 views
67

Voglio solo fare in modo che ho capito bene:ARC - Il significato di __unsafe_unretained?

  1. Devo __unsafe_unretain oggetti che io non possiedo?
  2. Se un oggetto è __unsafe_unretained Devo utilizzare assign nello @property? Significa che l'oggetto non viene mantenuto e fa semplicemente riferimento all'oggetto a cui lo assegno?
  3. Quando si desidera utilizzarlo ad eccezione dei delegati?
  4. È una cosa ARC o era in uso prima?

risposta

172

Il LLVM Compiler 3.0 introduce quattro nuove qualificazioni di proprietà: __strong, __autoreleasing, __unsafe_unretained e __weak. I primi tre sono disponibili anche al di fuori di ARC, come da the specification.

Come per Giosuè, per impostazione predefinita tutti i puntatori sono impliciti per essere __strong sotto ARC. Ciò significa che quando un oggetto viene assegnato a quel puntatore, viene mantenuto fino a quando quel puntatore fa riferimento ad esso. Questo va bene per la maggior parte delle cose, ma apre la possibilità di mantenere i cicli, come descrivo nella mia risposta here. Ad esempio, se si dispone di un oggetto che contiene un altro oggetto come variabile di istanza, ma tale secondo oggetto presenta un collegamento forte al primo come delegato, i due oggetti non verranno mai rilasciati.

Per questo motivo esistono i qualificatori __unsafe_unretained e __weak. Il loro uso più comune è per i delegati, dove si definisce una proprietà per quel delegato con l'attributo weak o unsafe_unretained (assign in modo efficace unsafe_unretained), quindi confrontarlo contrassegnando la rispettiva variabile di istanza con __weak o __unsafe_unretained. Ciò significa che la variabile di istanza delegata farà ancora riferimento al primo oggetto, ma non causerà il mantenimento dell'oggetto, interrompendo il ciclo di conservazione e consentendo il rilascio di entrambi gli oggetti.

Oltre ai delegati, questo è utile per interrompere qualsiasi altro ciclo di conservazione che potrebbe formarsi nel codice. Sicuramente, lo strumento Leaks ora include una vista Cicli, che mostra i cicli di mantenimento che scopre nell'applicazione in modo grafico.

Entrambi __unsafe_unretained e __weak impediscono la memorizzazione di oggetti, ma in modi leggermente diversi. Per __weak, il puntatore a un oggetto verrà convertito in nil sulla deallocazione dell'oggetto a cui punta, il che è un comportamento molto sicuro.Come suggerisce il nome, __unsafe_unretained continuerà a puntare alla memoria in cui si trovava un oggetto, anche dopo che era stato deallocato. Ciò può causare arresti anomali dovuti all'accesso a quell'oggetto deallocato.

Perché dovresti utilizzare mai __unsafe_unretained? Purtroppo, __weak è supportato solo per iOS 5.0 e Lion come target di distribuzione. Se si desidera tornare a iOS 4.0 e Snow Leopard, è necessario utilizzare il qualificatore __unsafe_unretained o utilizzare qualcosa come Mike's MAZeroingWeakRef.

+2

E naturalmente "__unsafe_unretained' può essere utile per definire array di C di costanti 'NSString' e simili, es 'NSString __unsafe_unretained * myStrings = {@" Foo ", @" Bar ", @" Baz ", nil};' – jlehr

+0

Grazie per l'ottima risposta. quando uso __unsafe_unretained iOS lo chiamerà come _weak se il sistema operativo del dispositivo è 5? o è impostato in fase di compilazione su xCode? – shannoga

+1

@shannoga - No, devi specificare manualmente "__weak" come un qualificatore per usare quel tipo di puntatori. Puoi ancora usare '__unsafe_unretained' con un target puramente 5.0 e non si comporterà come' __weak'. Se vuoi qualcosa che cambierà tra le due modalità a seconda che il tuo target lo supporti, potresti usare una definizione specifica del compilatore come suggerisco qui: http://stackoverflow.com/a/8594878/19679 –

4
  1. No, si potrebbe anche usare weak per gli oggetti che non ti appartengono.
  2. No, è possibile utilizzare anche unsafe_unretained nella proprietà.
  3. La mia comprensione è che gli articoli unsafe_unretained sono proprio come weak, senza la sicurezza aggiuntiva di eliminarli quando l'elemento che indicano viene rilasciato (e il sovraccarico che ne consegue).
  4. Questa è interamente una cosa ARC.
+0

In realtà, stranamente, gli iVars "unsafe_unretained", quando impostati in fase di runtime, si comportano proprio come quelli "forti", il che mi porta a credere che 'unsafe_unretained' sia semplicemente un suggerimento del compilatore, mentre debole non lo è. Maggiori informazioni qui: http://stackoverflow.com/questions/11621028/discovering-at-runtime-which-of-a-class-instance-variables-are-declared-weak#comment15389310_11621028 –

4

__unsafe_unretained è identico a quello che l'archiviazione predefinita di un oggetto era precedente a ARC. Con ARC il default è ora __strong, il che significa che hai un riferimento fino a quando il tuo riferimento non rientra nell'ambito.

1

Un'altra osservazione sulla __unsafe_unretained: ho crash nella mia app sul dispositivo e NON sul simulatore con Ivars dichiarati __unsafe_unretained! Sì, si trattava di un bug nel codice della migrazione ARC, ma era la prima volta che notavo una tale differenza tra dispositivo e simulatore.