sto scrivendo un'API che coinvolge gestione degli eventi, e vorrei essere in grado di utilizzare i blocchi per i gestori. I callback spesso vogliono accedere o modificare se stessi. In modalità ARC, Clang avverte che i blocchi di referenziamento di sé probabilmente creeranno un ciclo di conservazione, che sembra un utile avvertimento che voglio continuare in generale.modo compatto disattivare arco mantenere cicli di avvertimento da blocchi autoreferenziali
Tuttavia, per questa porzione del mio API, il ciclo di vita della richiamata e l'oggetto contenente vengono mantenuti esternamente. So che posso rompere il ciclo quando l'oggetto dovrebbe essere deallocato.
posso spegnere il conservano avvertimento ciclo su una base per file con #pragma clang diagnostic ignored "-Warc-retain-cycles"
, ma che disabilita l'avviso per l'intero file. Posso circondare i blocchi con un #pragma clang diagnostic push
e pop
intorno a quell'avviso, ma questo rende i blocchi brutti.
Posso anche fare in modo che l'avviso scompaia facendo riferimento a una variabile debole che punta al sé invece di fare riferimento direttamente a se stesso, ma che rende i blocchi molto meno piacevoli da usare.
La soluzione migliore che è venuta in mente è questa macro che fa la disabilitazione di diagnosi intorno al blocco:
#define OBSERVE(OBJ, OBSERVEE, PATH, CODE) \
[(OBJ) observeObject:(OBSERVEE) forKeyPath:(PATH) withBlock:^(id obj, NSDictionary *change) { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Warc-retain-cycles\"") \
do { CODE; } while(0); \
_Pragma("clang diagnostic pop") \
}];
che funziona, ma non è molto rilevabile per gli utenti API, non permette nidificato osservatori, e interagisce male con l'editor di XCode. C'è un modo migliore per disabilitare o evitare l'avviso?
Creare un riferimento '__weak' a' self' prende letteralmente una riga di codice. Penso che risolvere il problema in questo caso sia meglio che cercare di alleviare i sintomi. In che modo referenziare 'weakSelf' invece di' self' rendendo il blocco meno piacevole da usare? –
È meno piacevole in un paio di modi. Gli ascoltatori sono spesso piuttosto brevi, a volte una singola affermazione. La dichiarazione __weak raddoppia la dimensione dell'ascoltatore. Significa anche che è necessario qualificare gli accessi alle proprietà piuttosto che usare un sé dedotto. Concordo sul fatto che la mia soluzione attuale è probabilmente peggiore dell'utilizzo di __weak, ma speravo di ottenerne una migliore tramite questa domanda. –
È possibile modificare il prototipo del blocco di completamento per accettare un argomento "self"? Ora il codice in cui passi i blocchi apparirà lo stesso (ad eccezione dell'accettazione di un argomento in più) ed è possibile eliminare gli avvertimenti. (Ad esempio, se la tua API passa l'oggetto in questione al tuo blocco) – nielsbot