I was trying to create a static variable to store a dictionary of images. Unfortunately, the best way I could find to initialise it was to check in each function that used the variable. Since I am creating this variable inside a category, I can't just initialise it inside the initialiser. Is there a neater way of initialising navigationBarImages?
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) {
imageName=@"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
In C, static variables can only be initialized using constant literals.
A static variable in a block is initialized only one time, prior to program execution, whereas an auto variable that has an initializer is initialized every time it comes into existence. A static object of class type will use the default constructor if you do not initialize it.
In both C and Objective-C, a static variable is a variable that is allocated for the entire lifetime of a program. This is in contrast to automatic variables, whose lifetime exists during a single function call; and dynamically-allocated variables like objects, which can be released from memory when no longer used.
__attribute__((constructor))
static void initialize_navigationBarImages() {
navigationBarImages = [[NSMutableDictionary alloc] init];
}
__attribute__((destructor))
static void destroy_navigationBarImages() {
[navigationBarImages release];
}
These function will be called automatically when the program starts and ends.
Consider this approach,
static NSMutableDictionary *navigationBarImages()
{
static NSMutableDictionary *dict = NULL;
if(dict == NULL)
{
dict = [[NSMutableDictionary alloc] init];
}
return [[dict retain] autorelease];
}
then whenever you woulde use navigationBarImages, replace it with navigationBarImages(), like this:
change
NSString *imageName=[navigationBarImages objectForKey:self];
to
NSString *imageName=[navigationBarImages() objectForKey:self];
If the function call overhead bothers you, maybe use a temporary variable to catch the return of navigationBarImages(),
NSMutableDictionary *dict = navigationBarImages();
[dict doSomething];
[dict doSomething];
The drawback is once you called navigationBarImages(), the instance of NSMutableDictionary got created, then it'll never get chance to dealloc until the end of the program.
All you need is to set your static once at a known point before it is used. For example, you can set an NSApplication delegate and have it do the work in -applicationDidFinishLaunching:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With