Creating Protected and Private Variables in Objective-C Classeson 15 May 2011

Protecting class variables as represented by the Get a Mac ads and the security guard is watching over PCJava and other similar languages, including ActionScript, offer a very simple syntax for created protected and private variables. Protected meaning that any subclass can see and manipulate the variable or function. Private methods and variables will not be accessible to the subclasses. The syntax is to simply add a protected or a private statement before a variable or function.

protected function someMethod():void { ... }
private var somePrivateVar:int;
 

Easy, each is clearly defined as such. My experience with Objective-C in iOS has not offered that simplicity.

Protected and Private without the @synthesize

There is an easy way to create protected and private variables for a class. This method does not utilize the @synthesize directive that is part of Xcode. So memory management is completely up to you. I find this method works very well with variables that are not descendants of NSObject because there is no memory management needed.

The interface file (class.h) and inside the @interface declaration, add a @protected or @private. Anything that follows the line will be protected or private respectively. The key is not to add the @property line with the description for the variable, nor the @synthesize in the implementation file (class.m).

@interface PhotoViewer : UIView {
  NSArray *images; // protected by default
 
  @protected
  int index; // protected in class
 
  @private
  UIImageView *imageView; // will be private in class
  UIView *customView; // will be private in class
}

@end
 

Subclasses of this sample PhotoViewer class will be able to see the index variable, however they will not be able to see the imageView nor the customView. Additionally, because there is no @synthesize at play here, retaining variables by the class will have to be done manually. So setting the imageView would look something like

@implementation
- (id)initWithFrame:(CGRect)frame {
  self = [super initWithFrame:frame];
  if (self) {
    imageView = [[UIImageView alloc] init]; // retain count of 1
  }
  return self;
}

- (void)dealloc {
  [imageView release];
  [super dealloc];
}
@end
 

No need to go over memory management in any further depth, suffice it to say, the imageView in the example above has been allocd so it must be released in the dealloc otherwise the class will run into memory issues and not get released.

Everyone Needs to Know

Static variables. Thinking you can shorthand this and create variables directly in the implementation file would be correct. It works. However, creating variables in the implementation block will create a static variable. Static variables, are of course, shared with every instance of the class. So using the example class above, if we created index in the @implementation part of the file, every time a PhotoViewer was created and set the index = 0;, every instance would have an index equal to 0.

This can be really useful for many things, especially games where an enemy ship may need to know how many other ships there are. So if we used the class above and created a static variable, it would look like

@implementation

int numberOfPhotoViewers = 0; // static variable for PhotoViewer count

- (id)initWithFrame:(CGRect)frame {
  self = [super initWithFrame:frame];
  if (self) {
    imageView = [[UIImageView alloc] init];
    numberOfPhotoViewers++;
  }
  return self;
}

- (void)dealloc {
  [imageView release];
  [super dealloc];
}
@end
 

Not complicated, however it could cause a few problems if that was not expected behavior... and to me, was not.

If you enjoyed this, use this shorter link to share: http://the.ichibod.com/s/dnspp