2010-07-28 8 views
8

Estoy inmerso en el desarrollo de iOS mientras trato de comprender Objective-C y todavía estoy en esa fase en la que, donde quiera que mire, veo cosas que no tienen ningún sentido para un veterano programador en C como yo. En this Game Kit example on Apple's dev site, uno de los archivos de cabecera declara una interfaz de clase, tres momentos diferentes ...¿Por qué este ejemplo de código en el sitio de desarrollo de Apple declara tres interfaces para la misma clase?

@interface SessionManager : NSObject <GKSessionDelegate> { 
    NSString *sessionID; 
    GKSession *myGKSession; 
    NSString *currentConfPeerID; 
    NSMutableArray *peerList; 
    id lobbyDelegate; 
    id gameDelegate; 
    ConnectionState sessionState; 
} 

@property (nonatomic, readonly) NSString *currentConfPeerID; 
@property (nonatomic, readonly) NSMutableArray *peerList; 
@property (nonatomic, assign) id lobbyDelegate; 
@property (nonatomic, assign) id gameDelegate; 

- (void) setupSession; 
- (void) connect:(NSString *)peerID; 
- (BOOL) didAcceptInvitation; 
- (void) didDeclineInvitation; 
- (void) sendPacket:(NSData*)data ofType:(PacketType)type; 
- (void) disconnectCurrentCall; 
- (NSString *) displayNameForPeer:(NSString *)peerID; 

@end 

// Class extension for private methods. 
@interface SessionManager() 

- (BOOL) comparePeerID:(NSString*)peerID; 
- (BOOL) isReadyToStart; 
- (void) voiceChatDidStart; 
- (void) destroySession; 
- (void) willTerminate:(NSNotification *)notification; 
- (void) willResume:(NSNotification *)notification; 

@end 

@interface SessionManager (VoiceManager) <GKVoiceChatClient> 

- (void) setupVoice; 

@end 

veo que cada interfaz es diferente, pero especifique el mismo nombre de la clase.

  1. ¿Cuál es la razón de esto?
  2. También he notado este mismo comportamiento en otros ejemplos de código, solo que en lugar de declarar múltiples interfaces en el archivo de encabezado, verá un bloque @interface adicional declarado hacia la parte superior del archivo de implementación .m, típicamente sobre el @ Bloque de implementación. ¿Por qué?

¡Muchas gracias de antemano por su sabiduría!

Respuesta

9

Se llaman Categorías, y puede verlas entre paréntesis después del nombre de la clase.

Se utilizan para agrupar métodos en fragmentos en lugar de tenerlos todos en un grupo grande. También se pueden colocar separados de la declaración de clase principal. Esto es particularmente útil en archivos .m, donde puede necesitar crear métodos de utilidad para su clase, pero no quiere que sean visibles para otros objetos por ningún motivo (para que no los ponga en .h, que es importado por las otras clases). Otro uso común es agrupar métodos que corresponden a una cierta categoría lógica, protocolo informal, o lo que sea. Las categorías se pueden nombrar (@interface MyClass (MyCategory)) o anónima (@interface MyClass()). Este último generalmente se usa para métodos privados genéricos en su encabezado.

(La razón es necesario categorías para declarar métodos privados en su .m es por lo que el compilador sabe acerca de los métodos - de lo contrario, obtendrá una advertencia cuando intenta llamar a un procedimiento de este tipo.)

también , puede usar categorías para agregar métodos a las clases existentes. Por ejemplo, UIKit contiene una categoría en NSString llamada NSString (UIStringDrawing). O bien, si desea crear la suya propia:

@interface NSString (MyFoo) 
+ (NSString *)fooString; 
@end 
//... somewhere else... 
@implementation NSString (MyFoo) 
+ (NSString *)fooString { return @"foo!"; } 
@end 

Tenga en cuenta que no puede agregar variables de instancia con una categoría.

1

Esto es para el mantenimiento del código, creo ... es más fácil de ver a través de las diferentes interfaces etiquetadas, por ejemplo (VoiceManager) que es para la configuración del administrador de voz y métodos relacionados con eso, y usted tiene una interfaz que trata los métodos de delegado de GK y cualquier interacción con el juego de juegos ... en lugar de mirar un gran archivo de interfaz y tener que elegir lo que estás buscando ... También pueden dividir las implementaciones de esta manera, así que es más fácil para mirar y navegar

4

No está definiendo la interfaz 3 veces: solo hay una interfaz.

lo que está viendo son categorías que se suman los métodos de la clase

Hay una interfaz de base que define los atributos y algunos métodos - no es sólo uno de ellos hormiga que define la forma del objeto se almacena en la memoria y es el único que se necesita.

El objetivo C busca los métodos en tiempo de ejecución. No es necesario encontrar estos métodos en tiempo de compilación y, por lo tanto, no es necesario declararlos en los encabezados/interfaces, etc. Si no se declaran y los codifica, recibirá advertencias de tiempo de compilación.

En este caso, una categoría con un nombre vacío se utiliza para funciones privadas. Por lo general, solo pongo esta interfaz en el archivo .m de la clase, por lo que no es visible para otros códigos ni como encabezado.

La segunda categoría es agregar los métodos para hacer que SessionManager cumpla con el protocolo GKVoiceChatClient. La razón habitual para hacer esto es agrupar el código que cubre un comportamiento específico.

Otra razón para el uso de categorías es añadir métodos a una clase existente como NSString -Se puede crear su propia categoría añadiendo métodos sin la subclasificación de la clase en que tiene que hacer en muchos otros lenguajes orientados a objetos como Java y C++

1

En orden:

La primera declaración de interfaz es la declaración de interfaz real que declara la clase como una subclase de NSObject e implementa el protocolo GKSessionDelegate. También declara las variables de instancia y una selección de métodos.

La segunda declaración de interfaz es una extensión de clase. Se puede considerar como un tipo de categoría anónima. Así que lo omitiremos por ahora y volveremos a él.

La tercera interfaz es una declaración de categoría. Las categorías te permiten hacer dos cosas. Le permiten dividir la implementación de la clase entre múltiples archivos fuente. En lo anterior, tendrá

@implementation SessionManager 

// methods declared in the first @interface 

@end 

@implementation SessionManager(VoiceManager) 

// methods declared in the third @interface 

@end 

Las dos @implementaciones no necesitan estar en el mismo archivo fuente.

La otra cosa que una categoría puede hacer es permitirle extender clases ya existentes.e.g. @interface NSString(MyStringMethods)...

Volviendo a la extensión de clase, esto es un poco como una categoría anónima. Las implementaciones de los métodos declarados en él deben estar en el bloque principal @implementation. El propósito de la extensión de clase es permitirle declarar una API privada por separado del archivo de encabezado de la clase. Normalmente coloco uno en el archivo.m en la parte superior si tengo métodos que solo deberían usarse en la clase. Aunque, tenga en cuenta que esto es solo una restricción de tiempo de compilación. No hay nada que impida que alguien envíe un mensaje de extensión de clase en tiempo de ejecución.

Cuestiones relacionadas