Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialising a static variable in Objective-C category

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
like image 461
Casebash Avatar asked Jan 12 '10 02:01

Casebash


People also ask

Can static variables be initialized in C?

In C, static variables can only be initialized using constant literals.

Can we initialize static variable?

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.

What is a static variable in Objective-C?

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.


3 Answers

__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.

like image 149
kennytm Avatar answered Oct 18 '22 01:10

kennytm


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.

like image 28
yehnan Avatar answered Oct 18 '22 01:10

yehnan


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:

like image 32
Jon Reid Avatar answered Oct 18 '22 00:10

Jon Reid