Introduction
Objective-C is a programming language designed to enable sophisticated object-oriented programming; it is nothing more than a superset of the C programming language and it supports all the basic syntax of the C language, which means that theoretically a program written in C should compile as an Objective-C program without any change.
Most object-oriented environments which is provided for the development consist of several parts, some of them are:
- A language which is object-oriented programming
- A library of objects
- A package of development tools
- A runtime environment
What will you need?
I will not focus on building iPhone applications throughout this tutorial because first you learn the programming language used in the iPhone app development. This tutorial will concentrate more on the language (Objective-C) basic concepts and for that you just need a Mac with a compiler like GNU Compiler Collection (GCC).
If you have already installed the Xcode package and Interface Builder from Apple's Site then GCC was automatically installed. If not, then first you will need to register for an Apple Developer Connection account. Once you have registered, login and click Download Software then in Developer Tools you can download the required software.
Windows users (which is unlikely because this tutorial is written aimed at iPhone developers) can also compile Objective-C on your system using CygWin or the MinGW compiler.
Here you will learn the skills necessary to program in Objective-C using a style that is easy to follow, rich in examples and accessible to those who have never used Objective-C before.
Here we covered the fundamentals of Objective-C and object oriented programming. So, for that let's quickly look at the predefined Data Types and Operators of Objective-C.
List of data types and qualifiers supported by Objective-C
- int Data Type
- char Data Type
- float Data Type
- double Data Type
- id Data Type
- BOOL Data Type
Special Characters/Escape Sequences
- \a - Sound alert
- \b - Backspace
- \f - Form feed
- \n - New line
- \r - Carriage return
- \t - Horizontal tab
- \v - Vertical tab
- \\ - Backslash
- \" - Double quote (It is using when we want to place a double quote into a string declaration)
- \' - Single quote (It is using when we want to place a double quote into a string declaration)
Objective-C Data Type Qualifiers
- long
- long long
- short
- signed / unsigned
Now you we will look the list of Objective-C Operators
- Arithmetic Operators
Operator |
Description |
-(unary) |
Negates the value |
* |
Multiplication |
/ |
Division |
+ |
Addition |
- |
Subtraction |
% |
Modulo |
- Assignment Operators
- Compound Assignment Operators
Operator |
Description |
x += y |
It is used to Add x and y, and store result in x. |
x -= y |
It is used to Subtract y from x and store result in x. |
x *= y |
It is used to Multiply x by y and store result in x. |
x /= y |
It is used to Divide x by y and store result in x. |
x %= y |
It is used to Modulo on x and y and store result in x. |
x &= y |
Send the result to x of logical AND operation on x and y. |
x |= y |
Send the result to x of logical OR operation on x and y. |
x ^= y |
Send the result to x of logical Exclusive OR on x and y. |
- Increment and Decrement Operators
- Comparison Operators
Operator |
Description |
x == y |
True if x is equal to y. |
x > y |
True if x is greater than y. |
x >= y |
True if x is greater than or equal to y. |
x < y |
True if x is less than y. |
x <= y |
True if x is less than or equal to y. |
x != y |
True if x is not equal to y. |
- Boolean Logical Operators
Operator |
Description |
NOT (!) |
It simply inverts the current value of a boolean variable. |
OR (||) |
It returns 0 if both operands are not evaluates to true, otherwise one of its two operands evaluates to true it returns 1. |
AND (&&) |
It returns 1 only if both operands evaluate to be true. |
XOR (^) |
It returns 1 if one and only one of the two operands evaluates to true. |
- Ternary Operator
- Bitwise Operators
Operator |
Description |
Bitwise AND |
Used to comparison bit by bit of two numbers. |
Bitwise OR |
Used to comparison bit by bit of two binary sequences. |
Bitwise XOR |
Used similar as like OR operation, difference is that a 1 is placed in the result if one or other corresponding bit positions in the two numbers is 1. |
Bitwise Left Shift |
It moves each bit in a binary number a specified number of positions to the left. |
Bitwise Right Shift |
It moves each bit in a binary number a specified number of positions to the right. |
- Compound Bitwise Operators
Operator |
Description |
x &= y |
Apply a bitwise AND between x,y and send result to x. |
x |= y |
Apply a bitwise OR between x,y and send result to x.. |
x ^= y |
Apply a bitwise XOR between x,y and send result to x. |
x <<= n |
Shift x left by n places and send result to x. |
x >>= n |
Shift x right by n places and send result to x. |
Objective-C requires the interface, implementation and instantiation of a class to be in separately declared code blocks which use the file extensions (I will describe that in detail later in this article):
Extension |
Source type |
.h |
It holds the class, type, function, and constant declarations. |
.m |
It holds the source files and can contain both Objective-C and C code. |
.mm |
It contain C++ code in addition to Objective-C and C code. This extension should be used only if you actually refer to C++ classes or features from your Objective-C code. |
First Program: Welcome Objective C
Starting with a simple "Welcome Objective C" program as I am written this tutorial for iPhone Development, I choose Xcode for creating Objective-C programs. Start writing the program by launching Xcode; you just need to choose the "Foundation Tool" under "Command Line Utility" and give a name to your program. For example I chose here "WelcomeObjectiveC", now the project window will open and you will see the highlighted file, "WelcomeObjectiveC.m", start writing your program in this file.
Example
#import <Foundation/Foundation.h> int main (int argc, const char *argv[]) { NSLog (@"Welcome, Objective C"); return (0); } |
Now first build the program and then run it by clicking the Build and Go button or pressing . If there aren't any nasty errors in your program, Xcode successfully compiles and runs your program.
To see the output of your program, open the Xcode console window. You can open the console window by selecting Console from the Run menu or pressing .
And there you have the output in the console window:
Now see how the code works.
In the first line I import the Foundation.h file and this whole import statement informs the compiler to look at the Foundation.h header file in the Foundation framework.
Now you ask what is Foundation Framework? Ok, first see what is Framework: A framework is a collection of parts-header files, libraries, images, sounds, and more-collected together into a single unit.
Foundation Framework : The Foundation framework defines a base layer of Objective-C classes and the Foundation framework is designed with these goals in mind (said by Apple):
- It is provides a small set of basic utility classes used in the programs.
- Introduces consistent conventions such as Deallocation which make software development easier.
- Supports Unicode strings, object persistence, and object distribution.
- Provide a level of OS independence, to enhance portability.
Next is Main Function
int main (int argc, const char *argv[]) { //Function Code } |
The main function (as in standard C) tells the Objective-C compiler where to start program execution. In the main function you see the various fields as follows:
- return type : Specifies the data type of the result returned by the function. If the function does not return a result then void should be specified.
- function name : It is the name by which the function will be referenced when it is called from within the application code. Note that, unless otherwise specified using the static specifier, function names are global and must be unique within the context of an application to avoid compilation errors.
- argn type : The type of the argument passed through to the function.
- argn name : The name by which the argument is to be referenced in the function code.
Now comes to NSLog() and @"strings"
NSLog (@"Welcome, Objective C"); |
Here NSLog() is a Cocoa function which is used to print the value in Objective-C. In NSLog we pass the string between double quotes started with @ symbol that is represent as Objective-C language keywords.
After execution of main() is finished the zero value is returned by a "return (0);" statement which says that our program completed successfully.
Interface, Implementation and Instantiation
You can use Objective C to develop full fledged iPhone applications; it revolves around objects. It has three parts:
- Interface
- Implementation
- Instantiation
Interface
Interface is a object class in Objective-C, by convention, developers place the interface in a header file, it contains the class declaration and defines the instance variables and methods associated with the class. The interface is suffixed by .h, parentheses contained all the variables which is associated with the interface, but the methods are declared outside of the parentheses, yet still inside the structure formed by an opening @interface and a closing @end.
Structure of Interface
@interface Fraction: NSObject { // instance variables int numerator; int denominator; } -(void) setNumerator: (int) num; -(void) setDenominator: (int) den; -(void) print; @end //Fraction |
Code Walk
Start from the first line:
@interface Fraction: NSObject |
The above line of code informs the compiler that a new interface for a new class named Fraction is created and NSObject specifies that the Fraction class is based/inherited from the NSObject class.
{ // instance variables int numerator; int denominator; } |
Now to the template design; the above is a template we create within curly braces which is used to work with the Fraction object. Here we declare two elements numerator type-of integer and denominator again type-of integer, we can say they are instance variables to these elements.
When we talk about the variable declaration, first we need to tell the compiler what we're going to store and in what type-of. Here are some of the most important variables types that you should know about for now:
- int : For storing integers (numbers with no decimal point).
- char : For storing a character.
- float : For storing numbers with decimal points.
- double : Same as a float but double the accuracy.
Now come to method declaration.
-(void) setNumerator: (int) num; -(void) setDenominator: (int) den; -(void) print; |
The above code lines are just method declarations. In a method declaration you have to give the name of each method, the method's return type, and any
arguments. But the above code looks a little different; not a simple method declaration, isn't it? Yep, first remember that methods are of two types and the defining syntax is also two types:
- First which are defined using the plus sign (+)
- Second which are defined using the negative sign (-)
What is difference between these two methods? Methods which define using the plus sign (+) are class methods, they operate on all instances of the interface. They do not have access to any specific instance variables defined in the interface. Methods defined using the negative sign (-) are instance methods, they operate on a specific instance of the interface. They can access the variables associated with an instance of the interface.
Returning to the previous code, in the first two lines we just start the method declaration with a leading dash sign and the return type is in parentheses then the name of the method "setNumerator and setDenominator" then the trailing colon after the method name is a hint to compilers and humans that a parameter is coming next, then the type of the argument is in parentheses and at last the parameter name exists.
In the last line of the method declarations part we just print without returning anything.
We write the above line at the end; it ends the declaration of the Fraction class.
Implementation
After the interface declaration let's proceed to the implementation of the interface; as you have learned the interface only declares the class interface and not the methods themselves; the actual code is written in the implementation. Implementation (method) files normally have the file extension .m. Interface implementation is like definition of the interface. All implementations are contained within an @implementation.... @end block. One more thing that must be done when the implementation is done, that is importing the interface.
Structure of implementation
#import <Fraction.h> @implementation Fraction} -(void) print { printf( "%i/%i", numerator, denominator ); } -(void) setNumerator: (int) numN { numerator = numN; } -(void) setDenominator: (int) denD { denominator = denD; } @end |
Code Walk
Start from the first line:
As I already explained the Objective-C interface definition was contained in the file "Fraction.h". At the time of implementation we need to import this file at the beginning such as shown in the above code. Why? To include any module that creates an instance of the class, sends a message to invoke a method declared for the class, or mentions an instance variable declared in the class.
Implementation for class Fraction
In the above code @implementation is a directive which introduces the code for the guts of a class. After witting @implementation we write the name of the class. There is no trailing semicolon on this line, because you don't need semicolons after Objective-C directives.
Now define the individual methods
-(void) print { printf( "%i/%i", numerator, denominator ); } -(void) setNumerator: (int) numN { numerator = numN; } -(void) setDenominator: (int) denD { denominator = denD; } |
In the first line we print the values and you will see a sign of "%i" that is a formatting sign used because we were including an integer. Other variables have their own format specifiers:
- %i : integer
- %f : float
- %e : double
- %c : char
That actually implements the methods; in the above code we declared methods in the same manner as in the interface file, but without the semicolon. One thing more to notice here is that we renamed the parameters because it's better for the parameter names to differ between the @interface and the @implementation. Then inside the body of the method code will refers to the instance variables.
The last line:
Closes the block of implementation.
Instantiation
When you are using Objective-C on the iPhone you will need to allocate memory as well as create an object. To allocate memory you send an alloc message to the class itself; this process is called instantiating. When you instantiate an object, memory is allocated, and then that memory is initialized to some useful default values; that is, something other than the random values you get with freshly allocated memory.
Structure of Instantiation
int main( int argc, const char *argv[] ) { // creating a new instance Fraction *frac = [[Fraction alloc] init]; // set values [frac setNumerator: 2]; [frac setDenominator: 5]; // simple print printf( "The value of fraction is: " ); [frac print]; printf( "\n" ); // release the memory [frac release]; return 0; } |
Here the output will be:
The value of fraction is: 2/5 |
Code Walk
Instance Creation
Fraction *frac = [[Fraction alloc] init]; |
The above is how you instantiate an object, here we will use a constructor that is generally prefixed with the word "init" or simply init. An initializer returns an instance - usually the same instance, initialized. Therefore you can, and always should, call alloc and the initializer in the same line of code.
Set the values
[frac setNumerator: 2]; [frac setDenominator: 5]; |
The above code line is just simply calling the setNumerator and setDenominator method on frac, and passing it the parameter 2 and 5.
Printing
printf( "The value of fraction is: " ); [frac print]; printf( "\n" ); |
This is simply calling the print method on frac and prints the values/output.
Free the memory
When using Objective-C on the iPhone you must release objects that you have created using alloc, new or copy. This has to do with memory management. This is also functionally equivalent to C/C++; all three languaes do not use garbage collection. To release an object you simply send the "release" message to the object.
Let's Program with Multiple Parameters
In Objective-C you can use a method with multiple parameters. These parameters can be of the same type or of a different type.
Let's look at an example to clarify use of multiple parameters:
In class.h
#import<Foundation/NSObject.h> @interface Class:NSObject{ }
// declare method for multiple parameter -(int) sub: (int) i andj: (int) j andk:(int)k; @end |
The main thing is that the separator in the arguments are ":"; you can set any number of arguments using ":".
In class.m
#import<stdio.h> #import"Class.h" @implementation MyClass -(int) sub: (int) i andj: (int) j andk:(int)k; { return i+j+k; } @end |
In main
#import<stdio.h> #import"Class.m" int main() { Class *class = [[Class alloc]init]; printf("Subtraction is : %d",[class sub : 16 andj : 8 andk:5]); [class release]; return ; } |
The Output is:
Designated Constructor
Constructors are to create and initialize an instance of a class. For a class, there can be multiple constructors with various parameters expecting some initial variables. But in Objective-C, first you allocate memory on the heap. Next you call a method called an initializer, which is kind of Objective-C's equivalent of a constructor.
See the Example
Class Header : Employee.h
#import<Foundation/Foundation.h> @interface Employee : NSObject { NSString* name; int age; int mobileNumber; } |
Class Implementation : Employee.m
#import "Employee.h" @implementation Employee -(id)init { self = [super init]; if(self) { //Initialization code here. name=@""; age=0; mobilenumber=0; } return self; } @end |
Code Walk
First I created a standard Employee class; it does not consist of any methods, just some simple member variables; namely name, age, and mobilenumber.
Then in the implementation you see a method called "init". It is the standard initializer method that Xcode creates as a boilerplate for each new class file you create, this method is used to initialize a newly created object and put it into a safe state, exactly as constructors do in C# or C++.
Access Privileges
In Objective-C, access privilege can only be specified on variables. Default access in objective-C is @protected. Types of access privileges are:
- @public
- @private
- @protected
The @protected accessor enables access elements in the subclass.
Exception handling
Using GNU Compiler Collection (GCC) version 3.3 and later, Objective-C provides language-level support for exception handling. An exception is a special condition that interrupts the normal flow of program execution. There are a variety of reasons why an exception may be generated. It works like in every other modern language: they are represented by classes inheriting (usually) from NSException.
NOTE: Exception handling is only supported in Mac OS X 10.3
Compiler directives used for exception handling:
- @try: block which throws an exception.
- @catch: defines how to handle exceptions thrown by a try block; this is usually an NSException object.
- @finally: it is executed whether an exception is thrown or not.
- @throw: once your program detects an exception, it must propagate the exception to code that handles it. This code is called the exception handler. This entire
process of propagating an exception is referred to as "throwing an exception".
Exception-Handling Algorithm
mug *mug = [[mug alloc] init]; @try { [mug fill]; } @catch (NSException *exception) { NSLog(@"main: Caught %@: %@", [exception name], [exception reason]); } @finally { [mug release]; } |
Catching the Exception
@try { ... } @catch (CustomException *cex) { ... } @catch (NSException *nex) { // Processing necessary at this level.... } @catch (id uex) {... } @finally { // Processing necessary.... } |
Throwing Exceptions
NSException *exception = [NSException exceptionWithName: @"MugfullException"reason: @"The mug is full of water"userInfo: nil]; @throw exception; |
Inheritance
Inheritance brings something of a real-world view to programming. It allows a class to be defined that has a certain set of characteristics and then other classes can be created derived from that class. The derived class inherits all of the features of the parent class and typically then adds some features of its own. In addition to inheriting from classes we can also extend classes. When we extend a class, we take an existing class and add additional functionality to what is already available.
Letʼs understand the above diagram, first take NSMutableString. NSMutableString has NSString for a parent, meaning it inherits from NSString. Meanwhile, NSString has NSObject as a parent, so it inherits from NSObject, then NSMutableArray has NSArray for a parent, which means it inherits from NSArray. Meanwhile, NSArray has NSObject as a parent, so it inherits from NSObject, then the last NSNumber has NSValue for a parent, meaning it inherits from NSValue. Meanwhile, NSValue also NSObject as a parent, so it inherits from NSObject.
Is new technology nothing without new terms to learn? Exactly, so here are some new terms of inheritance:
- Super class : The superclass is the class you were inheriting from.
- Parent class : Another word for "superclass" is Parent class.
- Sub class : The subclass is the class doing the inheriting.
- Child class : Child class is another word for "subclass".
- Override : You override an inherited method when you want to change its implementation.
Let's take a Circle and Rectangle example of see how inheritance works. Look at the following figure, I am going to explain this by example:
In drawing.h
@interface drawing: NSObject { DrawShape bounds; } - (void) setBounds: (DrawShape) bounds; - (void) draw; @end // drawing |
In drawing.m
@implementation drawing - (void) setBounds: (DrawShape) b { bounds = b; } // setBounds - (void) draw { } // draw @end // drawing |
In Circle.h
@interface Circle : NSObject { DrawShapebounds; } - (void) setBounds: (DrawShape) bounds; - (void) draw; @end // Circle |
In Circle.m
@implementation Circle - (void) draw { NSLog (@"drawing a circle at (%d %d %d %d) in %@", bounds.x, bounds.y, bounds.width, bounds.height, } // draw @end // Circle |
In Rectangle.h
@interface Rectangle : NSObject { DrawShape bounds; } - (void) setBounds: (DrawShape) bounds; - (void) draw; @end // Rectangle |
In Rectangle.m
@implementation Rectangle - (void) draw { NSLog (@"drawing rect at (%d %d %d %d) in %@", bounds.x, bounds.y, bounds.width, bounds.height, } // draw @end // Rectangle |
In main
int main (int argc, const char * argv[]) { id shapes[2]; DrawShape shap1 = { 5, 5, 20, 40 }; shapes[0] = [Circle new]; [shapes[0] setBounds: rect0]; DrawShape shap2 = { 50, 60, 70, 80 }; shapes[1] = [Rectangle new]; [shapes[1] setBounds: rect1]; return (0); } // main |
In the output you will see:
Drawing a circle at (5 5 20 40)
Drawing a rectangle at (50 50 60 70)
Memory Management
In the Apple's library it says "The basic model used for memory management in a reference-counted environment is provided by a combination of methods defined in the NSObject protocol and a standard method naming convention. The NSObject class also defines a method, dealloc, that is invoked automatically when an object is deallocated."
For memory management you call [obj retain], which increases its "retain count" (number of references); and when you no longer need it, you call [obj release]. When the counter reaches zero, dealloc is then called.
Syntax of dealloc
-(void) dealloc { //Message of deallocation. printf( "Deallocing fraction\n" ); [super dealloc]; } |
Commonly used messages in memory management which you send to an abject are:
- alloc
- new
- retain
- release
- autorelease
- copy
Golden Rules of Cocoa memory management:
- Retaining the Object : Retaining the object means to increment the retain count of any object and send it the retain message. The retain message increments the object's reference count, and the release message decrements it.
- One more thing to remember to do is to release every object that you create with the "alloc" keyword.
- Releasing the Object : To decrement the retain count of any object, send it the release message.
Here I am giving an example of retainCount:
In NewClass.h
#import<Foundation/NSObject.h> @interface NewClass:NSObject // NewClass declaration. @end |
In NewClass.m
#import "NewClass.h" @implementation NewClass // NewClass definition. @end |
In main
#import "NewClass.m" #import <stdio.h> int main() { // objects in NewClass. NewClass *newClassObj1 = [[NewClass alloc] init]; NewClass *newClassObj2 = [[NewClass alloc] init];
// current internal count of the objects. printf("newClassObj1 retain count is : %d \n ", [newClassObj1 retainCount]);printf("newClassObj2 retain count is : %d \n\n", [newClassObj2 retainCount]);
// increment counts [newClassObj1 retain]; [newClassObj2 retain]; [newClassObj1 retain];
// print counts. printf("newClassObj1 retain count is : %d \n ",[newClassObj1 retainCount]);printf("newClassObj2 retain count is : %d \n\n ", [newClassObj2 retainCount]);
// Decrement counts. [newClassObj1 release]; newClassObj2 release]; [newClassObj1 release];
// print counts. printf("newClassObj1 retain count is : %d \n ",[newClassObj1 retainCount]);printf("newClassObj2 retain count is : %d \n ", [newClassObj2 retainCount]);
// now deallocate objects. [newClassObj1 release]; [newClassObj1 release]; return 0; } |
The Output is:
newClassObj1 retain count is : 1 newClassObj2 retain count is : 1
newClassObj1 retain count is : 3 newClassObj2 retain count is : 2
newClassObj1 retain count is : 1 newClassObj2 retain count is : 1 |
Protocol
A protocol in Objective-C is like interfaces in C#. It declares methods that can be implemented by any class. It is a way to require classes to implement a set of methods. We define a protocol much like a class or a category, it is essentially a list of methods. Protocol declarations look similar to a class declaration, they are frequently used to specify the interface for delegate objects.
Protocols are of the two types formal and informal. A formal protocol is declared with the @protocol directive; whereas informal protocols are actually categories, and declared as categories. So yes, it's odd but they use categories to implement informal protocols. The benefit of a formal protocol over informal is the compiler can 'type check' to ensure an object conforms to the protocol that's expected. With informal, it's up to the developer to ensure this.
Situations in which Protocols are useful:
- First it is used to declare methods that others are expected to implement.
- We can also use to declare the interface to an object while concealing its class.
- The third last but not least situation, used to capture similarities among classes that are not hierarchically related.
Methods in a protocol are required to be implemented in a class by default. But you can specify methods as optional too.
@protocol UserProtocol - (void) RMethod1; @optional - (void) OMethod1; - (void) OMethod2; @required - (void) RMethod2; @end |
Wrap Up
This is a basic overview of Objective-C. As you've seen, the language is pretty easy to pick up. There's not all about the language I am trying to cover only the basic syntax to learn.
If you like this small contribution, I am looking for your encouragement.