2011-01-29 6 views
29

Sapresti un modo per rendere una proprietà in sola lettura per chiamate esterne e readwrite per chiamate interne?Objective-C: (proprietà private/public) creazione di una proprietà in sola lettura per chiamate di classe esterne e readwrite per chiamate automatiche

ho letto tempo fa quacosa che sembrava

Nel .h

@property(nonatomic, readonly) NSDate* theDate; 

Nel .m

@interface TheClassName() 
@property(nonatomic, retain) NSDate* theDate; 
@end 

ma questo solleva un avvertimento quando si compila il .m "L'attributo della proprietà theDate nella continuazione della classe TheClassName non corrisponde alla proprietà class TheClassName".

In ogni caso, sembra funzionare (può leggere ma non impostato da fuori classe, può fare entrambi dall'interno) ma avrei dovuto perdere qualche tentativo di evitare l'avviso. Oppure se si conosce un modo migliore per farlo ...

risposta

62

Nel vostro .h:

@property(nonatomic, retain, readonly) NSDate* theDate; 

Nel vostro .m:

@interface TheClassName() 
@property(nonatomic, retain, readwrite) NSDate* theDate; 
@end 
+0

+1, potrebbe anche voler eliminare il 'readwrite' in quanto è il default e' nonatomic' finché non è veramente necessario? – zoul

+4

Il 'readwrite' rende esplicito che tu sai esattamente quello che vuoi. Alcune persone stanno portando avanti il ​​mantra "usa sempre' nonatomico' "da iOS a Cocoa (lo faccio certamente); potrebbe essere una politica estesa al progetto. – bbum

+1

Inoltre; il motivo per cui 'retain' deve essere menzionato in entrambi i casi è che i codegen per' @ synthesis' del getter di 'retain' vs.' assign' possono essere diversi in certi casi. Pertanto, la politica di 'retain' nella vista di sola lettura della proprietà * è * una parte dell'API/contratto della classe. – bbum

-2

Nel .m, non si dovrebbe mettere di nuovo @property. Non sono sicuro di quale effetto abbia, però. Intendevi usare @synthesize?

Si noti che la data verrà comunque letta/scritta all'interno dell'implementazione della classe, indipendentemente dal fatto che sia di sola lettura per il mondo esterno.

+1

sta usando un'estensione di classe. questo può essere usato per proprietà private, che possono essere semplicemente chiamate su 'self' http://stackoverflow.com/questions/4464112/best-practice-for-condensing-code/4465573#4465573 – vikingosegundo

+0

Non è chiaro se questo è ciò che Oliver sta cercando di ottenere, ma se lo è, allora questa è una buona risposta. Vikingosegundo, dovresti metterlo come risposta, e Oliver può accettarlo! – Dave

+2

chiede, come ottenere una proprietà pubblica di sola lettura, mentre c'è un'altra proprietà privata con accesso in lettura-scrittura. Non ho mai fatto una cosa del genere. Ho appena spiegato che sta usando un'estensione di classe, ma non risponde alla domanda. – vikingosegundo

-1

Se la proprietà è sostenuta da una variabile, la variabile è di lettura-scrittura dall'interno della classe di essere di default. Rendi la proprietà di sola lettura e il tuo obiettivo di progettazione sarà soddisfatto. All'interno della classe, fare riferimento alla variabile senza prepagare self..

+4

-1: Esistono molti ottimi motivi per utilizzare gli accessor anche quando fanno riferimento alle proprie variabili di istanza. (La gestione della memoria è una.) La domanda di Oliver è valida. – andyvn22

3

Questo problema viene in gran parte eliminato se ci si sposta su ARC. Invece di due dichiarazioni di proprietà, lo dichiareresti una volta nell'intestazione.

@property(nonatomic, readonly) NSDate* theDate; 

E quindi nell'estensione di classe, dichiarare semplicemente una variabile di istanza __strong.

@interface TheClassName() 
{ 
    __strong NSDate* _theDate; 
} 
@end 

e sintetizzarli in modo appropriato per l'attuazione

@implementation TheClassName 
@synthesize theDate = _theDate; 

Ora è possibile impostare la variabile di istanza.

_theDate = [NSDate date]; 

E ARC magicamente inline l'appropriato conservano funzionalità/release nel codice di trattarlo come un forte/mantenuto variabile. Questo ha il vantaggio di essere più veloce delle vecchie proprietà (ritenzione) e ARC allinea il codice di conservazione/rilascio in fase di compilazione.

+0

In questo caso, puoi anche lasciare _ il nome di iVar da solo.Il Datario emetterà un avviso poiché nessun sintetizzatore è stato sintetizzato e __strong ti impedisce di preoccuparti di impostare l'iVar in modo non corretto direttamente per errore. – Shinohara

+0

ma che cosa, se voglio che il setter o il getter esegua compiti addizionali, come le notifiche di trasmissione, il controllo di sanità? – vikingosegundo

+0

Quindi dichiarate la proprietà e scrivete il metodo getter o setter di cui avete bisogno, la dichiarazione __strong vi impedirà di implementare qualsiasi logica di conservazione/rilascio nel setter. – Shinohara

Problemi correlati