Preludio: Vale la pena entender la diferencia entre las directivas del precompilador y las constantes verdaderas. A #define
hace un reemplazo de texto antes de que el compilador construya el código. Esto funciona muy bien para constantes numéricas y typedefs, pero no siempre es la mejor idea para llamadas de función o método. Estoy operando bajo la suposición de que realmente quieres una constante verdadera, lo que significa que el código para crear la ruta de búsqueda solo debe ejecutarse una vez.
En el archivo MyClass.m, definir la variable y rellenarla en un método +initialize
así:
static NSArray *documentsDir;
@implementation MyClass
+ (void) initialize {
if (documentsDir == nil) {
documentsDir = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES) lastObject] retain];
}
}
...
@end
El static
modificador hace que sea visible sólo dentro de la compilación unidad donde está declarado. Para una constante simple, esto es todo lo que necesitas.
Si la clase tiene subclases, +initialize
se llama una vez para cada subclase (por defecto), por lo que querrá comprobar si documentsDir
es nil
antes de asignar a la misma, por lo que no perder memoria. (O, como señala Peter Lewis, puede verificar si la clase que se está inicializando actualmente es MyClass, usando ==
o el método -isMemberOfClass:
). Si las subclases también necesitan acceder a la constante directamente, necesitaría pre-declarar la variable como extern
en archivo MyClass.h (que incluyen las clases hijas):
extern NSArray *documentsDir;
@interface MyClass : NSObject
...
@end
Si pre-declara la variable como extern, debe quitar la palabra clave static
de la definición para evitar la compilación errores Esto es necesario para que la variable pueda abarcar múltiples unidades de compilación. (Ah, las alegrías de la C ...)
Nota: En código de Objective-C, la mejor manera de declarar algo tan extern
es utilizar OBJC_EXPORT
(un #define
declarados en <objc/objc-api.h>
), que se establece en función sobre si estás usando C++ o no. Simplemente reemplace extern
con OBJC_EXPORT
y listo.
Editar: Me acaba de pasar sobre un related SO question.
Gracias, pero cuando voy a construir mi proyecto, me sale el siguiente aviso: 'SearchPath' definido pero no se utiliza. La advertencia aparece en todos los archivos, excepto en aquellos en los que se usa directamente. El archivo con una constante definida se incluye en los encabezados precolombrados. ¿Hay alguna manera de deshacerse de esta advertencia? Gracias. –
Eso es porque el símbolo se está importando en varios archivos. Como el archivo en cuestión se está incluyendo en muchos otros archivos, use mi orientación sobre las subclases: declare la variable como extern en el encabezado, luego elija solo un lugar (en un archivo .m) para declararlo como estático, y uno (posiblemente diferente) lugar para inicializarlo. Si ya está haciendo eso y el error persiste, prefija la declaración de la variable con __attribute __ ((no utilizado)) para indicar al compilador que suprima las advertencias sobre los símbolos no utilizados. (Personalmente uso #define UNUSED __attribute __ ((sin usar)) como abreviación para esto. –
Tenga en cuenta que si MyClass está subclasificado, se llamará a la inicialización varias veces, por lo que si va a utilizar initialize, necesitará usar: if (self == [Clase MyClass]) { searchPath == ...; } –