2011-01-12 20 views
5

Básicamente, tengo (que se explica aquí: Objective-C Constants in Protocol) el siguiente códigoObjective-C ¿Es seguro sobreescribir [NSObject initialize]?

// MyProtocol.m 
const NSString *MYPROTOCOL_SIZE; 
const NSString *MYPROTOCOL_BOUNDS; 

@implementation NSObject(initializeConstantVariables) 

+(void) initialize { 
    if (self == [NSObject class]) 
    { 
     NSString **str = (NSString **)&MYPROTOCOL_SIZE; 
     *str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"size"]; 
     str = (NSString **)&MYPROTOCOL_BOUNDS; 
     *str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"bounds"]; 
    } 
} 

@end 

Me preguntaba: ¿Es seguro para mí tener una categoría que anula el método del NSObject +initialize?

+0

Primero, no necesita crear una categoría para hacer que la llamada en tiempo de ejecución sea 'inicializada', lo hará automáticamente antes de que se envíe ningún mensaje. En segundo lugar, ¿qué quieres decir con "seguro"? ¿Alguien lee la documentación más? –

+0

Mira la categoría ... Es una sobreescritura de la clase NSObject, no de mi clase. Estoy tratando de tener un método que sé que se llamará al comienzo de cualquier programa que utilice el marco que estoy creando. –

Respuesta

14

En resumen, no, no puede implementar de forma segura los métodos +initialize en las categorías de las clases. Terminará reemplazando una implementación existente, si hay una, y si dos categorías de una clase implementan el +initialize, no hay garantía que se ejecutará.

+load tiene un comportamiento más predecible y bien definido, pero es demasiado pronto para hacer algo útil porque muchas cosas están en un estado no inicializado.

Personalmente, omito +load o +initialize en total y utilizo una anotación de compilación para hacer que se ejecute una función al cargar el archivo binario/dylib subyacente. Aún así, hay muy poco que puede hacer de manera segura en ese momento.

__attribute__((constructor)) 
static void MySuperEarlyInitialization() {...} 

que son mucho mejor haciendo su inicialización en respuesta a la aplicación que está siendo criado. NSApplication y UIApplication ambos ofrecen ganchos de delegado/notificación para inyectar un poco de código en la aplicación cuando se inicia.

+0

¡Gracias! Pensé que tenía que haber algo así ... mi única pregunta es si esto funcionará para una biblioteca estática. –

+2

Sí, funcionará bien. Una biblioteca estática no es más que una colección de archivos .o que están vinculados a la aplicación como si estuvieran compilados en un principio. Tenga en cuenta, sin embargo, que no hacer la inicialización en tales constructores es un mejor plan a largo plazo .... – bbum

0

una variable de tipo NSString *const siempre va a ser inicializado antes de que acabe el código, asumiendo que ignoramos C caprichos ++ por el momento:

NSString *const MY_PROTOCOL_SIZE = @"..."; 

una variable de tipo const NSString * (el const palabra clave se aplica a las entrañas de la NSString , no su dirección) puede ser modificado por cualquier código, pero no puede haber mensajes enviados a él. Se derrota el propósito de hacerlo const. Considere lugar una función global:

static NSString *GetMyProtocolSize(void) { 
    return [[MyClass someStringLoadedFromAFile] ...]; 
} 

o utilizar un método de clase:

@implementation MyClass 
+ (NSString *)myProtocolSize { 
    return [[MyClass someStringLoadedFromAFile] ...]; 
} 
@end 

hecho una pregunta anterior acerca de por qué sus const cadenas no aceptarían valores dinámicos - esto es porque no lo hace parece entender lo que const hace a un símbolo. Debe leer el significado de la palabra clave const en C y debe buscar otro enfoque para obtener sus cadenas si const no es el correcto.

2

¿Por qué no configura esas dos variables dentro de la clase MyClass? Y también, ¿por qué no usas accessors? En lugar de tener una variable constante falsa que proviene de la nada, es preferible definir un descriptor de acceso en una clase que realmente debería usarlo. Un simple + (NSString *) myProtocolSize; sería genial, incluso en el protocolo.

Además, reemplazar los métodos de una clase en una categoría "funciona" pero no es confiable y debe evitarse a toda costa: si el método que está reemplazando se implementa en una categoría, el tiempo de ejecución NO garantiza la carga orden y su implementación podría nunca agregarse a ella.

+0

En realidad, hay más de 20 constantes, y la creación de una clase es realmente insostenible. –