Objective-C Classes
These notes describe the basics of defining your own custom Objective-C
classes and memory managment.
Defining a Class
A class definition is split into two files: an interface (.h) and an implementation (.m).
Example:
The interface file MyClass.h
#import < ....>
@interface MyClass : NSObject
{
// instance variables
NSString *myVar;
}
// method declarations
-(NSString *) myVar; // getter for
the instance variable
-(void) setMyVar : (NSString *) value; // setter for the
instance variable
-(void) doStuff;
@end
The implementation file MyClass.m
#import "MyClass.h"
@implementation MyClass
-(NSString *) myVar {
return myVar;
}
-(void) setMyVar : (NSString *) value {
myVar =
value;
}
-(void) doStuff {
...
}
@end
Calling your own methods
Consider the method doStuff which uses the class setter method. The keyword self is used to call your own method.
-(void) doStuff {
[self setMyVar: @"stuff"];
}
What if this method overrides the method of the super class? In that case,
you may want to let the super class do what needs to be done first.
-(void) doStuff {
[super doStuff]; //
super class method call
[self setMyVar: @"stuff"]; //
custom behavior
}
Synthesized Accessor Methods
The getter and setter methods can be synthesized, or basically written for you, as a convenience using the @property directive.
The interface file MyClass.h
#import < ....>
@interface MyClass : NSObject
{
// instance variables
NSString *myVar;
}
@property NSString *myVar;
-(void) doStuff;
@end
The implementation file MyClass.m
#import "MyClass.h"
@implementation MyClass
@synthesize myVar
-(void) doStuff {
...
}
@end
You can access the properties using a convenient dot syntax. Instead of [myObject
myVar] we can now use myObject.myVar to get the value. Instead of [myObject
setMyVar: value] we can use myObject.myVar = value;
Attributes can be included to property declarations as explained in the
documentation.
Allocating and Returning Objects
Object Creation is a two step process. First you allocate memory use the alloc method and then you initialize the object state with the init method.
MyClass *myObject = [[MyClass alloc] init];
You can write your own init method for the class that would do the initialization from the super class and then any specific initialization for your own class.
-(id) init {
if (self = [super init]) {
myVar =
@"initial value";
}
return self;
}
Important : For every alloc there must be a dealloc, otherwise
you will be leaking memory.
We need to discuss some memory management now. Memory management is done with a mechanism called
reference counting. Every object that is created has a retain count.
The alloc and copy methods create objects with a retain count of 1. There
are also methods retain and release which increment and decrement
the retain count for an object. When the count reaches 0, the object is
destroyed by having the dealloc method invoked automatically. You will
never invoke the dealloc method yourself but instead use the release method.
So we will need to write the dealloc method for our class.
-(void) dealloc {
//clean up code will need to release
instance variables that are owned by the class
[myVar release];
// invoke the dealloc of the super
class
[super dealloc];
}
Now we will examine returning newly created objects from our methods. Consider the following code:
-(NSString*) createString {
NSString *result;
result = [[NSString alloc]
initwithFormat: @"%@ %@", myVar1, myVar2];
return result;
}
This will leak memory! Why?
The memory for result needs to be release but where? We could insist the
the user releases the value that it received but this is bad form. It can't be
released before the return but it can't be released after either. We will
use a method called autorelease.
-(NSString*) createString {
NSString *result;
result = [[NSString alloc]
initwithFormat: @"%@ %@", myVar1, myVar2];
[result autorelease];
return result;
}
There is a pool of memory called the autorelease pool. An object is added to the pool when it is sent the autorelease message. When the pool is released, so are all the objects that were added to it. You may have observed the creation and destruction of the pool in your main program from the last lab.