2009-06-27 24 views

risposta

39

I due sintassi scopi diversi.

una categoria denominata - @interface Foo (FooCategory) - viene generalmente utilizzato per:

(1) estendere una classe esistente con l'aggiunta di funzionalità. Esempio: NSAttributedString in Foundation viene esteso da una categoria in AppKit che aggiunge un'API di formattazione del testo simile a RTF specifica per AppKit.

(2) dichiarare un insieme di metodi che possono o non possono essere attuate da un delegato. Esempio: varie classi dichiarano - ma non implementano - @interface NSObject (SetODelegateMethods).

Form (2) è caduto in disgrazia, ora che @protocol è stato esteso per supportare i metodi @optional in Objective-C 2.0.

Un'estensione di classe - @interface Foo() - è progettato per consentire di dichiarare ulteriore API private - SPI o Sistema Programming Interface - che viene utilizzato per implementare le interiora di classe. Questo in genere appare nella parte superiore del file .m. Qualsiasi metodo/proprietà dichiarato nell'estensione di classe deve essere implementato nell'implementazione @, proprio come i metodi/proprietà trovati nell'interfaccia pubblica @.

estensioni di classe possono essere utilizzati anche per ridichiarare un @property sola lettura pubblicamente readwrite prima @ synthesize'ing le funzioni di accesso.

Esempio:

foo.h

@interface Foo:NSObject 
@property(readonly, copy) NSString *bar; 
-(void) publicSaucing; 
@end 

Foo.m

@interface Foo() 
@property(readwrite, copy) NSString *bar; 
- (void) superSecretInternalSaucing; 
@end 

@implementation Foo 
@synthesize bar; 
.... must implement the two methods or compiler will warn .... 
@end 
+0

Non la barra @synthesize; linea significa che il compilatore genererà i due metodi (getter e setter) per la barra? – Elliot

+2

Sì, ma solo il getter è dichiarato nell'intestazione pubblica, il setter è dichiarato privatamente per l'uso all'interno della classe stessa. Questo non è C++, se vuoi introspettare il runtime puoi scoprire che il setter è lì e chiamarlo dove vuoi, ma a meno che tu non lo faccia esplicitamente riceverai avvertimenti di compilazione se cerchi casualmente di impostare la proprietà. –

+0

@Louis è corretto. La seconda proprietà sovrascrive quella "readonly" nella proprietà .h del file specificando "readwrite", quindi è ciò che il compilatore effettivamente fa. Tuttavia, solo il getter è visibile alle persone incluso il file di intestazione, poiché quando importano il file vedranno solo la versione "readonly" della proprietà. –

2

Sì,

vi sono le seguenti differenze.

1) Uso categorie anonimi richiede applicazione suoi metodi nel blocco @implementation principale per la corrispondente classe; le categorie anonime consentono di dichiarare un'API richiesta aggiuntiva per una classe in posizioni diverse dalla classe primaria blocco @interface

2) Quando si utilizza MyClass (privato), è necessario tenere presente quanto segue: oggetto/categoria denominata coppie deve essere unico. Se dichiari una categoria privata nella tua classe, non ci sono problemi. Tuttavia, le cose sono diverse sulle classi esistenti. Ad esempio, solo una categoria NSString (privata) può esistere in un determinato spazio dei nomi Objective-C. Questo può portare a problemi perché lo spazio dei nomi Objective-C è condivisa tra il codice del programma e tutte le biblioteche, quadri, e plug-ins.This è particolarmente importante per Objective-C programmatori che scrivono screensaver, pannelli delle preferenze, e altri plug-in perchè il loro codice verrà iniettato nell'applicazione o nel codice quadro che non controllano.

+0

Sei sicuro che sia il caso che le categorie devono essere un nome univoco? Ho capito che finché i selettori sono unici, non ci saranno conflitti. Il runtime è a conoscenza delle categorie? (il riferimento al runtime non li menziona) – rpetrich

+0

Non è la categoria che deve essere denominata in modo univoco: è la coppia oggetto/categoria che deve.Prova a compilare due diverse categorie NSString (private), anche utilizzando metodi diversi in uno dei tuoi progetti e verifica se funziona. –

+0

Hmm ... sembra che il compilatore/linker non permetta categorie duplicate su una classe, ma il runtime lo fa. È possibile definire le categorie NSDictionary (NSDictionary) o NSError (NSErrorPrivate) con un metodo di caricamento + e il compilatore, il linker e il runtime si comporteranno tutti come previsto (anche se Foundation.framework implementa entrambe le categorie internamente). Se si implementa una categoria denominata in un'intestazione come NSString (NSStringExtensionMethods), il compilatore emetterà avvisi, ma il linker e il runtime continuano a comportarsi come previsto. Niente di tutto questo è effettivamente utile nel mondo reale. – rpetrich

Problemi correlati