Objective-C

2. Objective-C: Objects, Methods, Classes

  • You own a phone.
  • Your phone is an object.
  • Your phone could be a Nokia, Samsung or Apple, etc.
  • Your phone is an instance of a phone.
  • Phone is a class from which your instance was created.
  • Each time a new phone is made, a new instance from the class of phone is made and each instance of the phone is an object.
  • Your phone may have different functionality and look; it may be plastic, metal, etc.
  • You perform certain functions with your phone; you make calls, you text, you write e-mail, etc.

Object, Method

Your Phone, Make a call Your Phone, Send a text Your Phone, send an e-mail Your Phone, charge.

Instances and Methods

  • Unique occurrence of class is an instance, actions performed on instances are methods.
  • Some methods can be applied to the instance only or to the class itself. I.e. finding out how many phones Nokia makes would apply to the class but recharging the phone would be an instance method.
  • Each object contains information about initial characteristics on construction but also the current characteristics. These can change dynamically during the life of the object/instance.

Objective-C syntax for applying methods to classes and instance:

[ ClassOrInstance method ];
  1. Left bracket followed by name of class or instance of the class.
  2. Followed by spaces then followed by the method you wish to perform.
  3. It is finally closed with a right bracket and a terminating semicolon.

When asking a class or instance to perform an action, you are sending it a message. The recipient of that message is called the receiver. Within the outlined format:

[ receiver message ];

Using the previous table:

yourPhone = [Phone new]; // Get a new phone

Sending a new message to the Phone class (the receiver) asking for a new car. The object (becoming the unique instance) is stored in yourPhone. This is now used to reference the unique instance of the phone from the factory.

new is a class method. The rest of the actions on the unique instance will be instance methods, applicable only to the unique instance.

[yourPhone prep]; // Prepare your phone for first time use
[yourPhone charge]; // Charge your phone
[yourPhone call]; // Make a call
[yourPhone send_e-mail]; // Send an email
[yourPhone send_sms]; // Text from your phone
currentCharge = [yourPhone battery_status];

The last entry, currentCharge, is an instance method that returns information. This will return the current charge level of the battery. We store it within the variable currentCharge.

A method taking an argument can be [yourPhone setLockCode: 1234]; // Sets the lock password to 1234

An Objective-C Class for Working with Fractions

1. Procedural Implementation

#import <Foundation/Foundation.h>

int main (int argc, const char* argv[])

{

@autoreleasepool {

int numerator = 1;

int denominator = 3;

NSLog (@”The fraction is %i/%i”, numerator, denominator);

}

return 0;

}

2012-02-10 20:07:06.270 prog1[16626:707] The fraction is 1/3

2. Class Implementation

#import <Foundation/Foundation.h>

// @interface to the class

@interface Fraction: NSObject

-(void) print;

-(void) setNumerator: (int) n;

-(void) setDenominator: (int) d;

@end

// @implementation within the class

@implementation Fraction

{

intnumerator;

intdenominator;

}

-(void) print

{

NSLog(@”%i/%i”, numerator, denominator);

}

-(void) setNumerator:(int)n

{

numerator= n;

}

-(void) setDenominator:(int)d

{

denominator = d;

}

@end

// @@@ Main program

int main (int argc, const char* argv[])

{

@autoreleasepool {

Fraction *myFraction;

// Declare instance of fraction

myFraction = [Fraction alloc];

myFraction = [myFraction init];

// Set fraction to 4/5

[myFraction setNumerator: 4];

[myFraction setDenominator: 5];

// Display fraction using internal print method

NSLog (@”Fraction is:”);

[myFraction print];

}

return 0;

}

Output:

2012-02-10 20:14:22.185 prog1[16728:707] Fraction is:

2012-02-10 20:14:22.190 prog1[16728:707] 4/5

Program ended with exit code: 0

Explanation

Program is logically divided into three sections:

  • @interface section
  • @implementation section
  • program section

The @interface section DESCRIBES the class and it’s methods. @implementation DESCRIBES the data (instance variables etc), and contains code to implement the methods declared in the @interface section. The final section being program contains the main program to carry out the purpose of the program.

One can also declare instance variables for a class within the interface section. Declaring within the implementation section is considered a better way to do it.

Each of these sections is part of every Objective C program. Each section is typically within its own file.

@Interface Section

When defining a new class. You have to tell the compiler where the class came from. Name the parent class. Then you have to define the operations – methods – to be used when working with objects created from this class. Items called properties are also listed within the @interface section.

@interface NewClass: ParentClass
propertyAndMethodDeclarations;
@end

Convention states class names begin with an uppercase letter.

Class and Instance Methods

You must define methods to work with your Fractions class. You will not have direct access to the internal variables in the instance. You have to write methods to set the variables within the instance, in the previous case – numerator and denominator. You also wrote a method called print that displays the value of the fraction.

-(void) print;

The minus sign tells the compiler that the method is an instance method. The only other option is a plus sign, which indicates a class method. A class method performs an operation on the class itself, like creating a new instance of the class.

An instance method performs operations on an instance (the unique object) of a class, like setting values, displaying etc.

Return Values

When declaring a new method, you have to tell the compiler if the method returns a value and what type it is. Enclose the return type in parentheses after the leading minus or plus sign. For example, this returns an integer:

-(int) currentAge;

This returns a double precision value:

-(double) returnDouble;

A value is returned using the return statement. If the method returns no value you indicate this using void.

-(void) print;

This declares and instance method called print that returns no value. You do not need to execute a return statement at the end of the method in this case. You can also execute a return without any value legally too.

return;

Method Arguments

Two other methods were declared in the @interface on the previous program:

-(void) setNumerator: (int) n; -(void) setDenominator: (int) d;

These are instance methods that return no value. Each method accepts an integer argument as indicated by the (int) in front of argument name. When a method accepts an argument, you append a colon to the method name when referring to the method. Therefore, setNumerator: is the correct way to identify the method which takes an argument. Identifying print without a trailing colon indicates that the method does not accept any arguments.

@implementation section

@implementation section contains code for methods declared in @interface section. You must specify the type of data to be stored in the objects of the class. Describe the data that members of the class will contain. These members are called instance variables.

Declare the methods in the @interface section and Define them in the @implementation section.

The general format for @implementation is:

@implementation NewClass{
memberDeclarations;
}
methodDefinitions;
@end

NewClass is the same name used for the class in the @interface section. You can use trailing colon followed by the parent class name, like the @interface section. @implementation Fraction: NSObject. However, this is optional and typically not done.

memberDeclarations section specifies what type of data is stored in a ParentClass, along with the names of those data types. Members declared here; int numerator; are known as instance variables. Each time you create a new object, a new and unique set of instance variables are created. They are internal variables only applicable to that instance Instance1 of parentClass and Instance2 of parentClass will have independent copies of each instance variable.

The program section

The program section contains code to solve the particular problem, which can be spread out across many files. A main routine must exist. This is where the program begins execution.

Define a variable called myFraction. The asterisk in the declaration says that myFraction is a pointer (reference) to a Fraction object. The variable does not store the data it stores a reference – a memory address – indicating where the object’s data is located in memory.

Fraction *myFraction;

myFraction defined as an object of type Fraction. Creating the actual object of Fraction. Ask the factory for a new object:

myFraction = [Fraction alloc];

alloc being short for allocate. This allocates memory for the new Fraction. The expression sends a MESSAGE to the Fraction class – [Fraction alloc].

myFraction = [myFraction init];

The init method initializes the class instance. The message is sent to the object you created – the unique instance. The init method returns a value — the initialized object. Here, we store the initialized class in the myFraction variable.

It is possible to combined the two line operation of allocating the new instance of a class and initializing it:

myFraction = [[Fraction alloc] init];

This can be taken further and can be shortened to have allocation and initialization within the declaration statement:

Fraction *myFraction = [[Fraction alloc] init];

Setting the values of variables within the class:

[myFraction setNumerator: 1];

[myFraction setDenominator: 3];

The first message statement sends setNumerator: message to myFraction. The supplied parameter is value 1. Same again with the second line for setDenominator.

Accessing Instance Variables and Data Encapuslation

Need to flesh out

Objective-C

1. Objective-C: First out the gate, building the first app

Using X-Code.
“Create a New Xcode Project” from startup screen (or File->New->New Project).
Command Line Tool application type.

Product name: prog1
Company identifier: Whatever!

Ensure that Foundation is select as the Type.
Ensure Use Automatic Reference Counting is selected.

Choose your location for your project.

Left hand pane, main.m. Open this and use this as the home for the first app.

  • Extension; Meaning
  • .c; C language source
  • .cc, .cpp; C++ language source
  • .h; Header file
  • .m; Objective-C source
  • .mm; Objective-C++ source
  • .pl; Perl source
  • .o; Object (compiled) file

The first application:

//
//  main.m
//  prog1
//
//  Created by Duncan Bowring on 1/15/12.
//

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{

@autoreleasepool {

// insert code here...
NSLog(@"The first app");

}
return 0;
}

Under the View toolbar menu, middle icon is to show the window which will display the program output. Mouse tooltip should say “Hide or show the Debug area”.
Xcode should display this window whenever anything is written to the debug area. Here is the output from the first app:

2012-01-21 19:45:52.626 prog1[1355:707] The first app

 

Program Explanation

  • Objective-C the code is case sensitive.
  • White space doesn’t matter; Objective-C does not care where on the line the code is entered.
  • The first 6 lines of the program are comments. Comments are not executed by the compiler and are used to document the program for the person reading the source code.
    • Two ways of entering comments:
      • // (two slashes) which are for single line comments.
      • /* to begin a comment block; this marks the beginning of the block.
      • */ will mark the end of the comment block and terminate the comment.
        • Handy if you want multi line comments. /* Comments cannot be nested.
  • Next line of code tells compiler to find and process/include a file named Foundation.h.
    • This is a system file.
    • Foundation.h contains information about other classes/functions that are used later in the program.
  • main is a special name indicating where the program is to begin execution. int specifies the type of value main returns. It is an integer.
  • The contents of ( ) are for command line arguments which is part of the C language.
  • The main routine’s program statements are contained within the braces { }
  • @autoreleasepool
    • Anything executed within the { } is within a context called autorelease pool. The autorelease pool is a mechanism which allows system to manage the memory the application uses as it creates new objects.
  • The statement NSLog is called within the routine and has a string argument; @”The first app”. The @ sign and the “” makes this known as a constant NSString object. Without the @ you will be writing a constant C-style string. With it you are writing an NSString string object.
  • NSLog routine is an Objective-C function that logs the arguments. Before it logs them it displays date and time the routine is executed, the program name and other data relating to process.
  • All statements in Objective-C must be terminated with a semi-colon.
  • Final code statement is return 0;. – This tells main upon termination to return a status value of 0. 0 as a return code means the program ended without error.

Summary of the whole process:

  1. Start XCode.
  2. Create new project; File->New->New Project or Create New Xcode Project from startup screen.
  3. Type of application, select Application->Command Line Tool.
  4. Enter name of application and set type to Foundation. Ensure Use Automatic Reference Counting is checked.
  5. Select name for project folder and choose directory to store project files in.
  6. Left hand window, main.m. It may be hidden in the tree view. Click the file and type program into the edit window that appears in the rightmost pane.
  7. In toolbar, select middle icon under View. This will show Debug window. This is where program output will show.
  8. Build and run the application by clicking Run button in toolbar.
  9. If any compiler errors show here, change the program code and run it again.

Displaying Variable Values

NSLog can also display the variable values and results of computations.

int main (int argc, const char * argv[])

{

@autoreleasepool {

int sum;

sum = 10 + 15;

NSLog(@”The sum of 10 and 15 is %i”, sum);

}

return 0;

}

Program Output:

2012-01-21 20:25:32.175 prog1[2193:707] The sum of 10 and 15 is 25

Program ended with exit code: 0

int sum; declares the variable sum to be set up of type integer. All variables must be declared before they can be used.
Variable declaration tells the compiler how the program should use it. Type int can only hold integer values – basically a number without a remainder/floating point only.
The number 15 is added to the number 10 and the computational result is stored (as indicated by the = sign) in the variable called sum.
NSLog routine has two arguments enclosed within the ( ) brackets. These arguments are separated by the comma.
The first argument of NSLog is the string. We want to have the value of variable sum displayed after the constant string characters defined here. The % character is a special character that NSLog recognizes. The character immediately following the % sign specifies what type of value to display at this point in the string. The letter i signals that an integer is to be displayed. When NSLog finds %i within the first parameter (the string), it will display the value of the next argument to the routine. sum is the next argument to NSLog, the value is automatically displayed after the initial string of “The sum of 10 and 15 is “.

You can stack these. For example, you can have multiple %i %i %i %i within the first parameter (character string), and afterwards have , variable1, variable2, variable3, variable4 and it will display as such.

Some other Programming Exercises:

1. Write a program that displays the following text:

In Objective-C, lowercase letters are significant.
main is where program execution begins.
Open and closed braces enclose program statements in a routine.
All program statements must be terminated by a semicolon.

Source Code:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])

{

@autoreleasepool {

NSLog(@”In Objective-C, lowercase letters are significant.\nmain is where program execution begins.\nOpen and closed braces enclose program statements in a routine.\nAll program statements must be terminated by a semicolon.”);

}

return 0;

}

Code Output:

In Objective-C, lowercase letters are significant.

main is where program execution begins.

Open and closed braces enclose program statements in a routine.

All program statements must be terminated by a semicolon.

2. What output would you expect from the following program?

Source Code:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])

{

@autoreleasepool {

int i;

i = 1;

NSLog (@”Testing…”);

NSLog (@”….%i”, i);

NSLog (@”…%i”, i + 1);

NSLog (@”..%i”, i + 2);

}

return 0;

}

Code Output:

2012-01-21 21:45:24.596 prog1[2997:707] Testing…

2012-01-21 21:45:24.597 prog1[2997:707] ….1

2012-01-21 21:45:24.599 prog1[2997:707] …2

2012-01-21 21:45:24.600 prog1[2997:707] ..3

3. Write a program that subtracts the value 15 from 87 and displays the result, together with an appropriate message.

Source Code:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])

{

@autoreleasepool {

int sum;

sum = 8715;

NSLog (@”87 – 15 = %i”,sum);

}

return 0;

}

Code Output:

2012-01-21 21:49:14.405 prog1[3093:707] 87 – 15 = 72

 

4. Identify the syntactic errors in the following program. Then type in and run the corrected program to make sure you have identified all the mistakes:

Source Code:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])

{

@autoreleasepool {

INT sum;

/* COMPUTE RESULT //

sum = 25 + 37 – 19

/ DISPLAY RESULTS /

NSLog (@’The answer is %i’ sum);

}

return 0;

}

Answer:

  • Upper case INT; should be lower case.
  • No close to quote block; // instead of */
  • No semicolon ending statement after computation; sum
  • Invalid single line quote; / instead of //
  • No double quote for character string as first parameter of NSLog.

Correct Source Code:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])

{

@autoreleasepool {

int sum;

/* COMPUTE RESULT */

sum = 25 + 3719;

// DISPLAY RESULTS /

NSLog (@”The answer is %i”, sum);

}

return 0;

}

Code Output:

2012-01-21 21:55:31.080 prog1[3238:707] The answer is 43

 

Onto 2.