Bookmark and Share

Objective-C Programming Tutorial


SoBackSanA


1983 - Objective-C (object-oriented extension of "C")
General-purpose, high-level.
Expanded on C, adding message-passing functionality based on Smalltalk language.
Creator: Brad Cox and Tom Love of Stepstone
Primary Uses: Apple programming
Used By: Apple's OS X and iOS operating systems





Chapter 1. Classes and Objects

This tutorial is written assuming you are already familiar with Object Oriented Programming either from C++ or Java.
So, I am not going to dive into the details of OO.

The basic code using classes and objects is divided into three parts.

  • main program
  • @interface
  • @implementation

The main program part does the real work using objects and their methods.
The @interface part describes the class with its members, data and method.
The @implementation part has the method implementations.




Main Program: <main.m>

#import <Foundation/Foundation.h>
#import "Rectangle.h"

int main (int argc, const char * argv[]) 
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    Rectangle *rect;
	
    rect = [Rectangle alloc];
    rect = [rect init];
	
    // set the values
    [rect setWidth: 10];
    [rect setHeight: 5];
	
    // print it
    [rect print];
     NSLog(@"Main: The area of a rectnagle with width = %i and height =%i is: %i", 
    [rect width],[rect height],rect.area );
   
    // free memory
    [rect release];
	
    [pool drain];
    return 0;		
}

The code above is Main Programming section.

  • Allocation and Initialization
    • Following three lines in the code:
      Rectangle *rect;
      rect = [Rectangle alloc];
      rect = [rect init];
    • can be replaced by:
      Rectangle *rect = [Rectangle new];
    • But it's better to use the two step allocation and initializateions:
      We are creating a new object and then we are initializing it.
  • What's NS in NSAutoreleasePool or NSLog?
    • The NS prefixes come from OpenStep, NeXT and Sun Microsystems's joint effort
      to make an open version of the NextStep API.
    • This project is eventually developed into Cocoa.
  • Member access
    • Using square bracket as in [rect width];
    • Using dot operator as in [rect.area];
    • Also, instead of [rect setHeight: 5], we can use
      rect.height = 5



@Interface: <Rectangle.h>

#import <Foundation/Foundation.h>

@interface Rectangle: NSObject 
{ 
	int width; 
	int height; 
	int area;
} 

-(void) print;
-(void) setWidth: (int) w; 
-(void) setHeight: (int) h;
-(int) area;
-(int) width; 
-(int) height; 
@end 

The code above is @interface declration.

  • Parent of Rectangle class is NSObject
    • The MSObject class is defined in the file NSObject.h,
      which is automatically included in the code when we import Foundation.h.
  • There are 3 instance variables in the Rectangle class.
  • There are 3 method in the Rectangle class: print, setWidth and setHeight.
    • The leading '-' sign tells the compiler that the method is an instance method. '+' sign means it's a class method.
    • We have two methods taking an argument:
      -(void) setWidth: (int) w;
      -(void) setHeight: (int) h;
      Each method returns no value and takes an integer as an argument.
      Notes that the trailing colon after the method name. It means the method is taking an argument.
    • We have one method taking no argument and not returning any value.
      -(void) print



@Implementation: <Rectangle.m>

#import "Rectangle.h"

@implementation Rectangle 

-(void) print 
{ 
	NSLog(@" Rectangle.m: The area of a rectangle with width=%i and height=%i is %i",
	width, height, self.area );
} 

-(void) setWidth: (int) w 
{ 
	width = w; 
} 

-(void) setHeight: (int) h 
{
 	height = h; 
} 

-(int) area 
{ 
	return width*height;
}

-(int) width 
{ 
	return width; 
} 

-(int) height 
{ 
	return height; 
} 
@end



Synthesized Accessor Method (@property and @synthesize)

Objective-C 2.0 provides a way to make setter and getter (or, if you prefer, accessor and mutator) methods automatically.
This is done by adding @property to the interface file and @synthesize to the implementation file.
The first step is to put @property directive in interface section to identify the properties.
These properties are instance variables in general. In our case, they are the variables "width" and "height".
I listed the new set of programs below with @property directive.


Main Program: <main2.m>

#import <Foundation/Foundation.h>
#import "Rectangle2.h"

int main (int argc, const char * argv[]) 
{
	
      NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
      Rectangle *rect =[Rectangle new];	
	
    //set the values
      [rect setWidth: 10];
    //[rect setHeight: 5];
    rect.height=5;	
    // print it
     [rect print];
     NSLog(@"Main: The area of a rectnagle with width = %i and height = %i is: %i", [rect width],[rect height],rect.area );
	
     // free memory
     [rect release];
	
     [pool drain];
     return 0;		
}

@Interface: <Rectangle2.h>

#import <Foundation/Foundation.h>

@interface Rectangle: NSObject 
{ 
	int width; 
	int height; 
	int area;
} 

@property int width, height;
-(void) print;
-(int) area;
@end 

As we see in the above @interface section, we no longer need the definitions for our getter and setter methods
such as "setWidth" and "setHeight". The compiler automatically will generate those for us.
Also note that we added a line "@synthesize width, height;" at "Rectangle2.m" file to make it work.
The line tells the compiler to generate a pair of getter and setter method for each of the two listed instance variables.
So, with @property and @synthesize, the compiler will make getter method: "width" and "height" and setter method: "setWidth" and "setHeight" for us.


@Implementation: <Rectangle2.m>

#import "Rectangle2.h"

@implementation Rectangle 

-(void) print 
{ 
	NSLog(@" Rectangle.m: The area of a rectangle with width=%i and height=%i is %i", width, height, self.area );
} 

-(int) area 
{ 
	return width*height;
}

@synthesize width, height;

@end

Sometimes, the @property keyword is followed by optional attributes, wrapped in parenthesis. These further define how the getters and setters will be created by the compiler. For example, in iPhone applications we use following line for Buttons:

@property (noatomic, retain)  UILabel *statusText;    
The meanings of those options are not that important here, I am just showing you that @property can have optional attributes. The attributes will be discussed in XcodeSDK for iPhone later.


SoBackSanB