Come si sostituiscono i riferimenti deboli quando si utilizza ARC e si sceglie come target iOS 4.0?


87

Ho iniziato a sviluppare la mia prima app iOS con Xcode 4.2 e puntavo a iOS 5.0 con un modello di "applicazione di utilità" (quello fornito con un FlipsideViewController).

Ho letto che poiché ARC è una funzionalità in fase di compilazione, dovrebbe essere compatibile anche con iOS 4, quindi ho tentato di indirizzare la mia app a 4.3 e provare a compilarla. Quando lo faccio, ottengo questo errore:

FlipsideViewController.m: errore: conteggio automatico dei riferimenti Problema: la destinazione di distribuzione corrente non supporta i riferimenti __weak automatizzati

Fa riferimento a questa linea:

@synthesize delegate = _delegate;

Quella variabile è dichiarata come:

@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;

Capisco che i "riferimenti deboli" non sono supportati in iOS 4, ma non capisco davvero perché dovrei voler utilizzare un riferimento debole per cominciare, né posso capire come riscrivere le cose per evitare di usarlo, mentre sfruttando ancora ARC (dopotutto, dovrebbe funzionare con iOS 4 E 5, giusto?)

Risposte:


149

Per indirizzare il vecchio sistema operativo, puoi usarlo unsafe_unretainedinvece che weaknella tua dichiarazione di proprietà e dovrebbe funzionare per lo più allo stesso modo. weaki riferimenti si annullano quando il loro obiettivo si allontana, ma unsafe_unretainedlascia aperta la possibilità che l'oggetto a cui stai collegando possa trasformarsi in un puntatore penzolante quando viene deallocato. Quest'ultimo è lo stesso comportamento come se avessi usato assigncome dichiarazione di proprietà nella gestione manuale della memoria.

Lo fai per evitare di mantenere i cicli, che ho menzionato nella mia risposta qui . Non vuoi avere un forte puntatore a qualcosa che potrebbe avere un forte puntatore all'oggetto originale. Quindi nulla verrebbe rilasciato correttamente.


Grazie per il consiglio. Dici "per indirizzare il vecchio sistema operativo ...". Ciò significa che dovrei usare unsafe_unretained solo nelle build dell'app precedenti alla 5.0? O posso semplicemente usare unsafe_unretained nel mio codice e crearlo per targetizzare sia 4.x che 5.x?
Mason G. Zhwiti

1
@Mason - unsafe_unretainedè supportato sia in iOS 4.x che in 5.0, quindi ti offre la retrocompatibilità. Se stavi realizzando una build solo 5.0, potresti passare a weakper sfruttare la sicurezza aggiuntiva che ti offre.
Brad Larson

Ho provato unsafe_unretained, ha funzionato comunque. Tuttavia, ho ricevuto molti avvisi come '"** __NSAutoreleaseNoPool (): Oggetto 0x564bd90 della classe __NSArrayM rilasciato automaticamente senza pool in posizione - solo perdite" *', è normale?
quinto

1
@fifth - Questo è un problema totalmente estraneo. Stai eseguendo qualcosa su un thread in background senza avere un pool di rilascio automatico in atto. I thread creati manualmente non hanno il proprio pool di rilascio automatico, quindi è necessario crearne uno da soli utilizzando @autoreleasepool(in ARC, NSAutoreleasePool per le implementazioni con conteggio dei riferimenti manuali precedenti).
Brad Larson

@ Brad, è utile, gli avvisi sono spariti, ho ricevuto diverse chiamate performSelectorInBackground.
quinto

11

Se si utilizzano solo riferimenti deboli per una maggiore sicurezza, chiamare manualmente le nuove funzioni di runtime se sono disponibili e in __unsafe_unretainedcaso contrario eseguire il fallback all'assegnazione semplice sulle variabili.

ZWRCompatibility.h semplificherà in qualche modo questo.


10

Grazie alla libreria di compatibilità PLWeakCompatibilty di Mike Ash , ora puoi semplicemente usare __weak anche su iOS 4.x.

È incredibilmente facile da configurare e non richiede considerazioni o sforzi aggiuntivi rispetto a 5.x.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.