2013-04-02 5 views
6

Ho un auto-sintetizzato readonly & weak proprietà:Prevenire ARC a zero un ivar debole subito dopo l'assegnazione (in build di rilascio)

@property (nonatomic, readonly, weak) KTWindowController* windowController; 

assegno l'ivar sintetizzato e quindi aggiungere in un array:

_windowController = [KTWindowController controller]; 
[self addSubController:_windowController]; 

Questo funziona bene in build di debug. Ma ho un report che in versione (ad hoc) costruisce questo immediatamente nil _windowController e poi tenta di aggiungere nil alla matrice, bloccando l'app.

Quale impostazione specifica (livello di ottimizzazione?) In una versione (ad hoc) di build modifica questo comportamento rispetto alle build di Debug?

Mi sembra strano che questo comportamento cambi da build di Debug a Release. Ma sono stato in grado di riprodurre questo comportamento, e in realtà ha senso - non solo quando non è coerente con ciò che accade nelle build di debug.

La soluzione suggerita:

KTWindowController* windowController = [KTWindowController controller]; 
[self addSubController:windowController]; 
_windowController = windowController; 

Altro che usare una variabile locale come visto sopra, ciò che soluzione mi consiglia, in casi come questi?

+0

Forse questa è una domanda stupida, ma perché stai assegnando direttamente a ivar invece di usare 'self.windowController = [KTWindowController controller]'? – bdesham

+0

La domanda ** è ** sciocca: la proprietà è in sola lettura. ;) – LearnCocos2D

+1

OK, abbastanza giusto ;-) – bdesham

risposta

1

Quando si dichiara una proprietà come deboli, si sta promettendo che alcuni l'altro oggetto si occupa della proprietà. Questo è ciò che significa deboli. Quando violate questo, accadono cose brutte. Così, ad esempio, quando si scrive:

KTWindowController* windowController = [KTWindowController controller]; 
[self addSubController:windowController]; 
_windowController = windowController; 

il gioco è soddisfare i vostri obblighi: il forte temporanea variabile windowController gestisce proprietà all'interno di questo metodo, e quindi windowController subController gestisce la proprietà dopo.

quando hai scritto

_windowController = [KTWindowController controller]; 

non stavi facendo quello che ha promesso di fare. _windowController è debole, quindi qualcun altro sta gestendo la vita. Ma guarda! Nessuno sta gestendo la vita! Quindi siamo liberi di sbarazzarci della variabile debole ogni volta che vogliamo. L'ottimizzatore guarda questo nella build della versione e dice,

Ehi! Questo tizio dice che non gli importa se questo controllore di finestre vive o muore, purché a nessun altro importa. Alcune persone! Ma non sono affari miei. Ma guarda questo: poiché non gli importa, non devo assolutamente farlo! O, in ogni caso, posso liberarmene nell'istante in cui lo faccio.

Il compilatore sta solo facendo quello che hai detto che volevi.

Sei sicuro di voler essere una proprietà debole? Ogni volta che vedo questo nel mio codice, mi preoccupo di verificare che la proprietà sia davvero debole; spesso, voglio comunque una proprietà forte.

0

Ho scoperto che la modifica del livello di ottimizzazione da None (-O0) a Fast (-O, O1) introduce questo problema.

As mentioned here, questo comportamento è normale. Dovrebbe davvero essere un avvertimento del compilatore.

ho finito per la fusione della linea supplementare nella soluzione spostando le assegnazioni ad una linea, questo funziona altrettanto bene:

// extra local var to prevent ARC from nil'ing the weak var right away in release 
KTWindowController* windowController = _windowController = 
               [KTWindowController controller]; 
[self addSubController:windowController]; 
+0

Quindi qual è lo scopo di avere la proprietà, se è inutilizzabile? –

+1

Non dovrebbe essere un avvertimento del compilatore, stai dicendo che vuoi assegnare un oggetto senza incrementare il conteggio dei ritagli perché ne hai solo bisogno mentre è usato da qualche altra parte e questa è un'affermazione perfetta, devi solo essere consapevole di quello che stai facendo. Quello che stai facendo è fare riferimento a una variabile forte, quindi manterrà fino a quando questa variabile non sarà eliminata. –

+0

@HotLicks Sono d'accordo, sarebbe più facile usare una proprietà 'readwrite strong', ma forse ha davvero bisogno che sia così. –