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.
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
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
@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 –