2010-01-12 13 views
8

Estaba intentando crear una variable estática para almacenar un diccionario de imágenes. Desafortunadamente, la mejor manera que pude encontrar para inicializarlo fue verificar cada función que usó la variable. Como estoy creando esta variable dentro de una categoría, no puedo inicializarla dentro del inicializador. ¿Hay alguna manera más clara de inicializar navigationBarImages?Inicializando una variable estática en la categoría Objective-C

static NSMutableDictionary *navigationBarImages = NULL; 

@implementation UINavigationBar(CustomImage) 
//Overrider to draw a custom image 
- (void)drawRect:(CGRect)rect 
{ 
    if(navigationBarImages==NULL){ 
     navigationBarImages=[[NSMutableDictionary alloc] init]; 
    } 
    NSString *imageName=[navigationBarImages objectForKey:self]; 
    if (imageName==nil) { 
     [email protected]"header_bg.png"; 
    } 
    UIImage *image = [UIImage imageNamed: imageName]; 
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; 
} 

//Allow the setting of an image for the navigation bar 
- (void)setImage:(UIImage*)image 
{ 
    if(navigationBarImages==NULL){ 
     navigationBarImages=[[NSMutableDictionary alloc] init]; 
    } 
    [navigationBarImages setObject:image forKey:self]; 
} 
@end 
+0

No recomiendo inicializar un objeto Obj-c con NULL, debe inicializarlo con nulo. –

+0

@DanielSanchez, aunque estoy de acuerdo, en realidad, nada es solo NULL lanzado como un objeto. –

+0

@FireLizzard nil es el equivalente de NULL para un puntero a un objeto. nil y NULL no deben ser intercambiables. NULL se define de manera diferente que nil. nil se define como (id) 0. NULL no es. –

Respuesta

24
__attribute__((constructor)) 
static void initialize_navigationBarImages() { 
    navigationBarImages = [[NSMutableDictionary alloc] init]; 
} 

__attribute__((destructor)) 
static void destroy_navigationBarImages() { 
    [navigationBarImages release]; 
} 

Estos función será llamada automáticamente cuando se inicia el programa y los extremos .

+2

Me gusta mejor que '+ initializer'. – neevek

+3

No lo entiendo ... ¿A dónde va esto? ¿Escrito así? ¿Y qué se supone que va a pasar? –

1

Una opción es usar C++. Cambie la extensión del archivo a .mm y reemplace = NULL con [[NSMutableDictionary alloc] init].

+0

¿Funcionará eso en el iPhone? – Casebash

2

Todo lo que necesita es establecer su estática una vez en un punto conocido antes de usarla. Por ejemplo, se puede establecer un delegado NSApplication y hacer que haga el trabajo en -applicationDidFinishLaunching:

+0

No puedo acceder a él en otro archivo; las variables estáticas solo se declaran dentro del alcance de una clase – Casebash

+2

Simplemente defina una función de configuración independiente. –

+1

No. Eso no funcionará * Algo * tiene que llamar a la función de configuración. – bbum

10

considerar este enfoque,

static NSMutableDictionary *navigationBarImages() 
{ 
    static NSMutableDictionary *dict = NULL; 
    if(dict == NULL) 
    { 
     dict = [[NSMutableDictionary alloc] init]; 
    } 
    return [[dict retain] autorelease]; 
} 

entonces cada vez que woulde utiliza navigationBarImages, reemplazarlo con navigationBarImages(), de esta manera:

cambio

NSString *imageName=[navigationBarImages objectForKey:self]; 

a

NSString *imageName=[navigationBarImages() objectForKey:self]; 

Si la sobrecarga llamada de función le molesta, tal vez utilizar una variable temporal para coger el retorno de navigationBarImages(),

NSMutableDictionary *dict = navigationBarImages(); 
[dict doSomething]; 
[dict doSomething]; 

El inconveniente es que una vez llamó navigationBarImages(), el instancia de NSMutableDictionary se creó, entonces nunca tendrá la oportunidad de dealloc hasta el final del programa.

+2

Esta vida es típica para las variables estáticas, sin embargo, Realmente no lo consideraría un inconveniente per se. –

+1

Esto no va a ser tan seguro como usar 'dispatch_once' para inicializar el diccionario.El código sería mejor utilizar: 'estática dispatch_once_t una vez; static NSMutableDictionary * dict = nil; dispatch_once (& once,^{dict = [[NSMutableDictionary alloc] init];}); return dict; ' – Streeter

0

Puede agregar +initialize en el archivo .m de su categoría; bastará con asegurarse de que no está destruyendo una implementación existente o obtendrá un éxito general. (Obviamente, usted puede estar seguro de esto si usted escribió el código, pero con código de terceros, esto probablemente no es el mejor enfoque.)

+1

... y ¿cómo vas a estar seguro? Mala idea. – benzado

+0

Sin duda, podría estar seguro si escribió la clase, o puede utilizar métodos de introspección en tiempo de ejecución o enfoques similares. Por lo general, solo uso + initialize en mi propia fuente, solo lo estaba publicando como una opción. Con frecuencia, * es * la mejor opción, pero no con categorías. –

+0

Si escribió la clase, no necesita poner + inicializar en una categoría. Si no lo escribió, no puede confiar en que no lo pisará en una versión futura de la biblioteca. Poner + inicializar en una categoría es más riesgoso de lo que vale. – benzado

Cuestiones relacionadas