Class Variables

I previously wrote about the lack of support for private methods when working with Objective-C. As part of that post I presented a few work-arounds. Along the same lines, there are is no support for class variables in Objective-C. This post will explore this a little further and walk through a short example that shows how you can use static variables to arrive at a similar result to working with class variables.

The reason for this discussion is that I recently had a need to track a few values that were tied to a specific class, not instances of the class. Given that using class variables was not an option, here’s what I did instead. First, I defined static variables for each value I needed to track. Next, I wrote methods that are private to the implementation to work with those values (think getter/setter). Caveat: there really is no such thing as a private method in Objective-C, however, you can arrive at a similar result as shown here: private methods.

The reason for choosing static variables is that the scope of these variables is limited to the class file where they are defined. In addition, static variables are not inherited by subclasses.

What follows is a short example where I use a static integer to track how many instances of a specific class are created. The interface for the class follows:

TestClass Interface

1
2
3
4
5
6
7
8
9
10
11
//  TestClass.h
//
#import <UIKit/UIKit.h>
 
@interface TestClass : NSObject 
{
}
 
+ (NSUInteger)instanceCount;
 
@end

Note that the instanceCount method is a class method. The implementation file for TestClass has a few interesting things to explore, have a look:

TestClass Implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//  TestClass.m
 
#import "TestClass.h"
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Static variables 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Count of objects allocated
static NSUInteger instanceCount;
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods defined
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@interface TestClass (private)
  +(void)bumpInstanceCount;
@end
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods implementation
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@implementation TestClass (private)
 
+(void)bumpInstanceCount
{
  instanceCount += 1;
}
 
@end
 
/*-------------------------------------
* TestClass implementation
*-------------------------------------*/
@implementation TestClass
 
- (id)init 
{
  if (self = [super init])
    [TestClass bumpInstanceCount];
 
  return self;
}
 
+ (NSUInteger)instanceCount;
{
  return instanceCount;
}
 
@end

On line 9 notice the definition of the static variable. This variable is only accessible from within this implementation file. On lines 14-16 I define a category as a means to create methods that are private to this implementation, that is, not directly exposed to the outside world as are the contents of TestClass.h. Inside the private implementation section I have written a class method to increment the static variable.

Beginning on line 33 is the code for the TestClass implementation. Worthy of noting is line 38 where upon initializing each new object of type TestClass I call the class method ‘bumpInstanceCount’ to update the count of TestClass objects created, that is, update our static (“class”) variable.

There is one more class method ‘instanceCount’ where I return the current value of the static variable (lines 43 – 46). Notice that this method is part of the TestClass implementation rather than the category for private methods. This is the only means of accessing the static variables from outside the class.

What follows is the App Delegate code for exercising TestClass:

AppDelegate Interface

1
2
3
4
5
6
7
8
9
10
11
//  UntitledAppDelegate.h
#import <UIKit/UIKit.h>
 
@interface UntitledAppDelegate : NSObject <UIApplicationDelegate> 
{
    UIWindow *window;
}
 
@property (nonatomic, retain) IBOutlet UIWindow *window;
 
@end

AppDelegate Implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//  UntitledAppDelegate.m
 
#import "UntitledAppDelegate.h"
#import "testClass.h"
 
@implementation UntitledAppDelegate
 
@synthesize window;
 
- (void)applicationDidFinishLaunching:(UIApplication *)application 
{    
  TestClass *tmp1, *tmp2;
 
  tmp1 = [[TestClass alloc] init];
  NSLog(@"instance count: %d", [TestClass instanceCount]);
  tmp2 = [[TestClass alloc] init];
  NSLog(@"instance count: %d", [TestClass instanceCount]);
 
  [tmp1 release];
  [tmp2 release];
}
 
- (void)dealloc 
{
  [window release];
  [super dealloc];
}
 
@end

The output looks as follows:

You can extend this concept to other data types as well, for example, give it a go by experimenting with a C structure or array.

If you are interested to learn more about using categories, look over here.

  1. Nice, concise explanation of how to implement static fields in an Objective-C class. Everyone should give a test harness like this when explaining concepts. It makes for easier and quicker understanding. Thanks!

  2. Excellent explanation of something I wanted explaining :) Just one final thought. I have a class/static variable that is a reference to a class, is there a good way of ensuring that this is released correctly?

  3. Put another way, if we use the Singleton pattern as an example, is there a good way in Objective C of releasing the class level reference to the one and only class created?

  4. While you are at it, you should suggest initializing the static variable before usage.

  5. Frank, Objective C guarantees to initialise all variables to 0 so initialising the static variable just wastes processor cycles. For interest C also initialises global variables to 0 but as it doesn’t initialise all variables to 0 I prefer to explicitly initialise all variables.

Comments are closed.