2011-11-01 16 views
6

Nel codice che sto ereditare, ho visto il seguente:Proprietà di sola lettura per IBOutlet Work e sarebbe preferibile?

@property (readonly) IBOutlet UIImageView * bgImage; 

Quando si aspetterebbe un conservano modello di memoria come:

@property (readonly, retain) IBOutlet UIImageView * bgImage; 

Sono confuso perché la prima definizione di proprietà funziona senza causare problemi.

Inoltre, v'è un release in dealloc come ci si potrebbe aspettare, come:

-(void)dealloc 
{ 
    [_bgImage release]; 
    [super dealloc]; 
} 

Ti sarei grato se qualcuno può trovare una spiegazione per questo. Ho parlato con lo sviluppatore originale e stava cercando di scrivere codice più conciso, motivo per cui ha omesso lo retain nel modello di memoria (sembrava inutile).

Mi chiedo se IBOutlet sia fondamentalmente trattato come un'istruzione IBOutlet di ivar perché è di sola lettura (nessun setter da utilizzare, quindi il modello di memoria di assegnazione predefinito non fa differenza).

Se non si prevede che IBOutlet cambi, l'utilizzo di una proprietà readonly senza modello di memoria sarebbe in realtà un modo preferibile per definire le proprietà?

risposta

7

Il caricatore pennino su iOS crea gli oggetti nel pennino e li autorizza automaticamente. Quando stabilisce le connessioni alle prese, utilizza setValue:forKey:, che chiamerà il metodo setter per quella chiave. Se nessun setter è definito, ad esempio quando IBOutlet è una proprietà readonly, l'oggetto viene mantenuto in ogni caso prima di essere assegnato. (questa è una parafrasi di Managing Nib Objects in iOS nella Guida alla programmazione delle risorse.)

Quindi, in realtà, che la presa è dichiarato come retain o assign, l'oggetto all'altro capo è proprietà dall'oggetto con l'uscita . O è mantenuto dal metodo setter, oppure viene mantenuto da setValue:forKey: quando non viene trovato un setter. Poiché nel secondo caso non vi sono altri possibili proprietari, è possibile considerare l'oggetto con il punto vendita come proprietario. Pertanto l'oggetto nel pennino dovrebbe essere rilasciato in dealloc.

Sono d'accordo con te che questa condizione di memoria dovrebbe essere resa esplicita modificando gli attributi di proprietà per includere retain. * Se non è readonly non sembra fare la differenza (tuttavia, vedi sotto). Concettualmente, sì, l'oggetto è di sola lettura, quindi se contrassegnarlo esplicitamente come tale dipende dal fatto che lo consideri adeguatamente documentato dal fatto che si tratta di uno IBOutlet.

UPDATE: Il commento di Paul.s mi ha spinto a fare un test rapido.Ho creato una sottoclasse UIView che registra i suoi alloc, retain, release, e autorelease chiamate, bloccato un'istanza di esso in un pennino, e ha dato l'applicazione delegato un IBOutlet tramite una proprietà.

Compattare manualmente l'attività di conteggio dei riferimenti, l'istanza è uscita con un conteggio netto 0 quando la proprietà era (readwrite, assign). Era netta +1 quando la proprietà veniva dichiarata come consigliata, (readwrite, retain) e anche quando era (readonly, assign). Tutto ciò è praticamente come previsto: quando è (readwrite, assign), il setter di assegnazione viene utilizzato per effettuare la connessione e non viene effettuato alcun ritocco. Quando è readonly, il meccanismo di connessione ricomincia a fare il proprio mantenimento. Più interessante, quando ho provato a bloccare l'applicazione cambiando il colore di sfondo di questa vista con la proprietà dichiarata (readwrite, assign) (ad esempio, quando era presumibilmente stata rilasciata), ho visto un'ultima chiamata al numero retain pop-up.

Penso che si tratti di questo: seguire la raccomandazione di Apple: sanno cosa sta succedendo dietro le quinte e (escludendo bug) non vi guideranno.

(Un'altra cosa da togliere è che, come sempre, preoccuparsi dei conteggi di riferimento assoluti non sarà molto utile - il conteggio è andato fino a 6 in un punto, nel corso di due dozzine di chiamate a retain e release - devi solo preoccuparti di conserva e rilascia che causano direttamente)


* Naturalmente, questo cambia sotto ARC.. Le informazioni che ho parafrasato sono nella sezione "Modelli legacy" del suo capitolo. Sotto ARC, la raccomandazione è IBOutlets per essere weak a meno che non siano di primo livello, nel qual caso dovrebbero essere strong. Operando in questo modo significa che ci si sta affidando alla gerarchia della vista (le viste che mantengono le loro sottoview) per mantenersi.

+0

'se la presa è dichiarata come conservata o assegnata, l'oggetto dall'altra parte è di proprietà dell'oggetto con la presa '(questo non è così chiaro) è solo se è impostato su' readonly'? Se fosse '(assign, readwrite)' allora sarebbe stato usato sicuramente il setter non-retainer e non sarebbe stato usato 'retain'? - Cito solo perché è l'unica parte della tua risposta ad essere un po 'ambigua –

+0

Penso di sì ... è certamente quello che sembra dire. –

+2

@ Paul.s: guarda il mio aggiornamento - Ho deciso di contare l'attività di riferimento a mano ei risultati sono stati, a mio avviso, istruttivi. –

2

Ho segnalato un bug con Apple che se si creano variabili di istanza IBOutlet invece di proprietà, Xcode creerà comunque automaticamente le versioni in dealloc ecc. Xcode per le app iOS sembra sempre creare versioni per IBOutlet sia che siano corrette o meno.

personale non mi piace proprietà IBOutlet in quanto significa che li dichiara come readwrite, il che significa che sono documentati come readwrite, ma la maggior parte del tempo, (quasi sempre), IBOutlet dovrebbe concettualmente essere di sola lettura. Ovviamente devono essere readwrite per impostare inizialmente.

+0

È possibile dichiarare '@property (nonatomic, readonly)' nell'interfaccia pubblica e '@property (nonatomic) IBOutlet' nell'estensione di classe. –

Problemi correlati