The Objective-C Language

A new language usually requires a full semester. We will cover the Objective-C language in two and a half weeks.

  1. Variables, including pointers and structures
  2. Functions and their arguments and return value
  3. Objects and messages. The messages have arguments and return value too.
  4. Classes of objects, and how to create objects
  5. Inheritance: the subclass is derived from the superclass.

Documentation:

  1. Apple’s Programming with Objective-C covers the language itself.
  2. Apple’s Concepts in Objective-C Programming covers the classes that Apple has written in the language.
  3. Wikipedia article on Objective-C.
  4. Translate Java to Objective-C: j2objc.

The language C has no expressions that start with the characters [, ^, or @, and no declarations that start with + or -. The language Objective-C is simply C with the addition of expressions and declarations that start with these characters. The Objective-C additions are therefore instantly recognizable by their initial character.

Variables

A variable is a container. There are many types of variables. For example,

Integers

An int variable can hold an integer (whole number). Each statement ends with a semicolon; each comment starts with a double slash. Case counts.

	//Create an integer variable named i and store 10 into it.
	int i = 10;
	//The name of a variable can be more than one letter.
	int width = 320;	//means 320 pairs of pixels on iPhone 5S
	int height = 568;
	//The above statements created new variables.
	//The following statement merely changes the value
	//of an existing variable.
	i = 3 + 4 * 5;
	//Change the value of i to 35;
	//override the "precedence" of the operators.
	i = (3 + 4) * 5;
	i = i + 1;	//Add 1 to the variable.  i now holds 36.
	i += 1;		//Easier way to do the same thing.  i now holds 37.
	++i;		//Even easier way (prefix increment).  i now holds 38.
	i++;		//I discourage you from using postfix increment.

Is there any way an increment can fail? The range of values for an int variable is centered (almost) around zero:

	int biggest  =  2147483647;	// 231 - 1
	int smallest = -2147483648;	//-231
That means that an int can hold any one of 4,294,967,296 = 232 possible integers.

Enumerations

We’ll need consecutively numbered integers to refer to the buttons on an alert view or action sheet. The Objective-C convention is to use embedded uppercase letters for compound words.

	int abortButton = 0;
	int retryButton = 1;
	int ignoreButton = 2;
	int failButton = 3;
	int destructButton = 4;

A list of enumerations is an easy way to mass-produce a series of consecutively numbered integer variables. By default, the numbers start at zero. The following code does approximately the same thing as the above.

	enum {
		abortButton,
		retryButton,
		ignoreButton,
		failButton,
		destructButton
	};

Unsigned integers

An int variable can hold any one of 4,294,967,296 = 232 possible values, centered at zero. An NSUInteger variable can hold any one of 18,446,744,073,709,551,616 = 264 possible values, starting at zero. When you run this example, be sure to select iPhone Retina (4-inch 64-bit) in the upper left corner of Xcode. NS stands for NeXTSTEP, software left over from Steve Jobs’s company NeXT. Follow the NS link to see a typical page of Apple’s documentation. We’ll be reading it all semester.

	int iBiggest  =  2147483647;		// 231 - 1
	int iSmallest = -2147483648;		//-231
	NSUInteger uBiggest = 18446744073709551615;	// 264 - 1
	NSUInteger uSmallest = 0;

An NSUInteger can never hold a negative number. An attempt to ram a negative number down its throat would result in wrap around.

	NSUInteger u = -1;	//Store 18446744073709551615 into u.
	u = -2;			//Store 18446744073709551614 into u.
	u = -3;			//Store 18446744073709551613 into u.

NSUIntegers are used for counting things. Early examples will be the count property of an NSSet and the count property of an NSArray. (Surprisingly, the index of an action sheet button is an NSInteger, not an NSUInteger. So are the number of sections in a UITableView, and the number of rows in each section.)

Booleans

A BOOL variable (after George Boole) is much more limited. It can hold one of only two possible values, YES and NO. Write them in all uppercase.

	BOOL decision = YES;
	decision = NO;

	//Toggle the decision.  Exclamation point means "the opposite of".
	decision = !decision;

Floats and doubles

Floats and doubles have room for a decimal point and digits to the right of the decimal point. CG stands for Core Graphics.

	int i = 3.14159;		//Store 3 into i.
	CGFloat f = 3.14159;		//A CGFloat can hold up to 6 significant digits.
	double d = 3.14159265358979;	//A double can hold up to 15 significant digits.

To hold the location of a pixel on the screen, a CGFloat will suffice. We won’t need the 15 digits of a double to hold a number in the range 0 to 320.

Pointers

Every variable has a memory address. We can get the address of the variable with an ampersand, chosen because the words “address” and “ampersand” begin with the same letter.

A pointer is a variable that can hold the address of another variable. The most important use of a pointer will be to point to (i.e., hold the address of) an “object”. But we haven’t seen any objects yet, so we will demonstrate with a pointer that points to an int. The following pi is a pointer of the specific type “pointer to int”. We have to declare (create, and announce the name of) the pointer with an asterisk.

	int i = 10;
	int *pi = &i;	//Store the address of i into pi.
			//We say that pi "points to" (i.e., holds the address of) i.
	CGFloat f = 3.14159;
	CGFloat *pf = &f;	//pf is a "pointer to CGFloat".
				//We say that pf "points to" (i.e., holds the address of) f.

Most of our strings will be Objective-C strings. But an SQLite database will reject an Objective-C string, so we will have to feed it a C string. A C string is a string (series) of characters stored in consecutive bytes of memory. A pointer will to a C string will actually be a pointer to the first character of the C string.

	//p is a variable of type "pointer to char".
	//It points to the 'H' in the C string Hello.
	//The 'e' is in the byte of memory next to the 'H'.
	//The first 'l' is in the byte of memory next to the 'e'.  Et cetera.
	char *p = "Hello";

For “strong” vs. “weak” pointers, see View Controller.

Structures

A big variable that contains little variables is called a structure. The little variables inside the structure are called the fields of the structure. Think of them as the structure’s internal organs.

CGPoint and CGSize are two types of structure that happen to have the same number of fields and the same data type for corresponding fields. But the structures are used for totally different purposes. The fields of a CGPoint might be negative, but the fields of a CGSize should never be negative. (CG stands for Core Graphics.)

	CGPoint p = CGPointMake(0.0, 0.0);	//The structure p holds the values 0.0 and 0.0
	CGSize s = CGSizeMake(320.0, 568.0);	//The structure s holds the values 320.0 and 568.0

The fields inside a CGPoint are named x and y. Write the name of the structure variable to the left of the dot, and the name of the field to the right.

	CGPoint p = CGPointMake(0.0, 0.0);
	CGFloat x = p.x;
	CGFloat y = p.y;

The fields inside a CGSize are named width and height.

	CGSize s = CGSizeMake(320.0, 568.0);
	CGFloat w = s.width;
	CGFloat h = s.height;

In the location manager example, the fields inside a CLLocationCoordinate2D structure will be named latitude and longitude. CL stands for Core Location. A structure is not limited to containing only two fields. A tailor might need a structure containing bust, waist, hips. A weather report might need a structure containing temperature, humidity, barometric pressure, and wind speed.

A structure can contain smaller structures as its fields. For example, a CGRect contains a CGPoint named origin and a CGSize named size.

	CGRect rect = CGRectMake(0.0, 0.0, 320.0, 568.0);	//x, y, width, height
	CGPoint p = rect.origin;	//The fields inside of rect
	CGSize s = rect.size;		//are named rect.origin and rect.size

	//An expression can have more than one dot,
	//like the expression 10+20+30 has more than one plus.
	CGFloat x = p.x;
	CGFloat y = rect.origin.y;

Here’s a diagram of the above structure rect and its contents.

Functions

In every language, a program may be divided into sections. In some languages, these sections are called subroutines. In other languages, they are called procedures. In this language, they are called functions.

Every function has a name; examples are sqrt, sin, cos, tan. Get used to sine and cosine if you want to do computer graphics. To call (execute or invoke) a function, write a pair of parentheses after the function’s name.

	//Call a function named f.
	f();

To send one or more arguments (pieces of information) to the function, write them in the parentheses.

	//Call a function named f.  Pass it one argument.
	f(10);
The following example sends one argument to NSLog, a function that will print debugging output in the Console window of Xcode. The argument in this example is a string (series) of characters. A string is always enclosed in "double quotes". To make this string immutable (unchangeable), i.e., an NSString as opposed to some other kind of string, write an @ in front of it. Click on this link to see that NSLog will accept only an NSString, not any other kind of string.

	//Call the function NSLog.  Pass a string to it.
	NSLog(@"Arrived at the start of the main function.");

Multiple arguments are separated with commas.

	//Call a function named f.  Pass it three arguments.
	f(10, 20, 30);

	//Call a function named CGPointMake.  Pass it two arguments.
	CGPoint p = CGPointMake(0.0, 0.0);

The function NSLog often takes multiple arguments. The three most important % formats in its first argument are %d, %g, and %@.

	//Pass two arguments to NSLog.

	int i = 10;
	NSLog(@"The value of i is %d.", i);			//d for int; it stands for "decimal"
	CGFloat f = 3.14159;
	NSLog(@"The value of f is %g.", f);			//g for CGFloat and double
	NSString *s = @"This is a string.";
	NSLog(@"The value of s is %@.", s);			//@ for NSString

But there are many more % formats; see the following example and the complete list. CHAR_BIT is the number of bits per byte. sizeof gives us the number of bytes in a variable. Their product is the number of bits in the variable. The number of bits might depend on whether you have a 32- or 64-bit device.

	int i = 10;
	NSLog(@"The value of i is %d.", i);			//d for decimal
	NSLog(@"The address of i is %p.", &i);			//p for pointer
	NSLog(@"The number of bytes in i is %zu.", sizeof i);	//z for size_t, u for unsigned
	NSLog(@"The number of bits in i is %zu.", CHAR_BIT * sizeof i);
2014-02-04 16:11:05.444 Project[47920:a0b] The value of i is 10.
2014-02-04 16:11:05.446 Project[47920:a0b] The address of i is 0x7fff5fbfed0c.
2014-02-04 16:11:05.446 Project[47920:a0b] The number of bytes in i is 4.
2014-02-04 16:11:05.447 Project[47920:a0b] The number of bits in i is 32.

If you select iPhone Retina (4-inch 64-bit) in the upper left corner of Xcode, your CGFloat will occupy 64 bits of memory.

	CGFloat f = 3.14159;
	NSLog(@"The value of f is %g.", f);			//g for CGFloat and double
	NSLog(@"The address of f is %p.", &f);			//p for pointer
	NSLog(@"The number of bytes in f is %zu.", sizeof f);	//z for sizze_t, u for unsigned
	NSLog(@"The number of bits in f is %zu.", CHAR_BIT * sizeof f);
2014-02-04 16:13:03.777 Hello[50841:a0b] The value of f is 3.14159.
2014-02-04 16:13:03.779 Hello[50841:a0b] The address of f is 0x7fff5fbfed08.
2014-02-04 16:13:03.779 Hello[50841:a0b] The number of bytes in f is 8.
2014-02-04 16:13:03.780 Hello[50841:a0b] The number of bits in f is 64.
	//Pass three arguments to NSLog.

	CGPoint p = CGPointMake(0.0, 0.0);
	NSLog(@"p == (%g, %g)", p.x, p.y);			//g for CGFloat and double
	CGSize s = CGSizeMake(320.0, 568.0);
	NSLog(@"s == %g × %g", s.width, s.height);
	//Pass five arguments to NSLog.

	CGRect r = CGRectMake(0.0, 0.0, 320.0, 568.0);
	NSLog(@"r == (%g, %g), %g × %g",
		r.origin.x,
		r.origin.y,
		r.size.width,
		r.size.height
	);

Some functions give us a return value (answer or result). We can store the return value into a variable.

	//Call the sqrt function.  Store its return value (1.414213562373115) into s.
	double s = sqrt(2.0);

	NSLog(@"The square root of 2.0 is %g.", sqrt(2.0));

We have already seen several functions with return values:

	CGPoint p = CGPointMake(0.0, 0.0);
	CGSize s = CGSizeMake(320.0, 568.0);
	CGRect rect = CGRectMake(0.0, 0.0, 320.0, 568.0);

The first ones we will see under actual combat conditions will be NSStringFromClass and UIApplicationMain.

	return UIApplicationMain(argc, argv, nil, NSStringFromClass([ProjectAppDelegate class]));

Objects and messages

An object is a thing to which you can send a message. To send a message to an object, write the object on the left, the message on the right, and enclose them in [square brackets]. The object is said to be the receiver of the message. Only an object can receive a message. The variables we have seen so far—int, NSUInteger, BOOL, CGFloat, double, structures, pointers—cannot receive messages.

	[spartans prepareForGlory];	//300 (2007)
	[luke useTheForce];		//Star Wars (1977)
	[hal openThePodBayDoors];	//2001: A Space Odyssey (1968)
	[gort klaatuBaradaNikto];	//The Day the Earth Stood Still (1951)
	[rick hideMe];			//Casablanca (1942)
	[dorothy surrender];		//The Wizard of Oz (1939)
	[super init];		//the first real example we'll see in Objective-C

There are many classes (types) of objects. The name of a class always begins with an uppercase letter. For example, let’s temporarily assume that rick is an object of class BogieCharacter.

There’s another way in which an object is different from an integer, BOOL, CGFloat, or even a structure. Each of these little things can be stored in a variable. But an object is too big to be stored in a variable. Only the address of the object can be stored in a variable.

The “object” rick, for example, is not an object at all. It is merely a variable that holds the address of an object. The object is the thing that is of class BogieCharacter. rick is merely a variable of type “pointer to BogieCharacter”, analogous to the variable of type “pointer to int” we saw above. Since rick is a pointer, it must have been declared with the asterisk shown below. We ask you to accept on faith that the value of the expression [[BogieCharacter alloc] init] is the address of an object of class BogieCharacter.

	int i = 10;
	int *p = &i;

	BogieCharacter *rick = [[BogieCharacter alloc] init];

id

A variable of type “pointer to BogieCharacter” can hold only one type of thing: the address of an object of class BogieCharacter. But a variable of type id is flexible enough to hold the address of an object of any class. An id is a pointer, even though it is declared without an asterisk.

	id p = rick;		//Store the address of a BogieCharacter into p.
	p = dorothy;		//Store the address of a GarlandCharacter into p.
	p = signorUgarte;	//Store the address of a PeterLorreCharacter into p.

Messages and methods

  I don’t deny there is a remarkable quantity of ivory—mostly fossil. We must save it, at all events—but look how precarious the position is—and why? Because the method is unsound.  

Joseph Conrad, Heart of Darkness, Chapter III

An object can have functions. The functions that belong to an object are called the methods of that object. Most of the functions that we call will be methods. Only occasionally will we call a function such as sqrt, which is an orphan that belongs to no object.

When we send a message to an object, we are really calling the method that has the same name. For example, when we send the message hideMe to the object pointed to by rick, we are really calling the method hideMe that belongs to that object. (From now on, we will refer to this object as rick, even though rick is really the name of the pointer, not of the object. The object actually has no name.)

Return value of a method

A function can send us back a return value.
	double s = sqrt(2.0);
Similarly, when we call a function that is a method, we can get back a return value. For example, when we call the bounds method of the screen object s, we get back a return value which is a structure of type CGRect. We store the structure in the variable b of type CGRect. (We ask you to accept on faith that [UIScreen mainScreen] is an expression whose value is the address of an object of class UIScreen.)

	//Let s be a pointer to the main screen of the app.
	UIScreen *s = [UIScreen mainScreen];

	//Get the location and size of the screen.
	CGRect b = [s bounds];

Incidentally, because bounds is a “property” as well as a method, there’s a shortcut. A property of an object can be accessed with the same dot with which we accessed a field of a structure.

	//Get the location and size of the screen.
	CGRect b = s.bounds;	//easier way to do the same thing

Arguments of a method

We saw that an argument passed to a function is written in parentheses.

	double s = sqrt(2.0);

An argument passed to a method is written after the name of the method, preceded by a colon. The colon is actually part of the name of the method.

	[rick hide: me];		//the name of the method is hide:
	[rick hide: myChips];
	[rick hide: theLettersOfTransit];
	[luke use: theForce];
	[hal open: thePodBayDoors];
	[myObject gotoX: 10];		//the name of the method is gotoX:

A method that takes multiple arguments

  Ilsa: How nice, you remembered. But of course, that was the day the Germans marched into Paris.
Rick: Not an easy day to forget.
Ilsa: No.
Rick: I remember every detail. The Germans wore gray, you wore blue.
 

Casablanca (1942)

We can send more than one argument to a method. The following method is named gotoX:y: and takes two arguments, each preceded by a colon. The number of colons in the name of a method indicates how many arguments the method takes.

	[myObject gotoX: 10.0 y: 20.0];

The method named gotoX:y:z: takes three arguments. The first and second arguments break the name of the method into three pieces.

	[myObject gotoX: 10.0 y: 20.0 z: 30.0];

Other methods that take two arguments:

	[ilsa theGermansWore: gray youWore: blue];
	[captainRenault andTheNamesAre: mr and: mrsVictorLaszlo];
	[strasser iWasWillingToShoot: captainRenault andImWillingToShoot: you];

A method that takes a variable number of arguments

If the method takes a variable number of arguments, separate them with commas. The method stringWithFormat:, for example, takes a first arguments that is a printf-style format string like the first argument of NSLog.

	int month = 12;
	int day = 31;
	int year = 2014;

	int hour = 18;
	int minute = 30;
	int second = 0;

	//Four arguments
	NSString *s = [NSString stringWithFormat: @"%d/%d/%d", month, day, year];

	//Seven arguments
	NSString *t = [NSString stringWithFormat: @"%d/%d/%d %02d:%02d:%02d",
		month, day, year, hour, minute, second];

	//v = "Today's date is 12/31/2014."
	NSString *u = @"Today's date is ";
	NSString *v = [u stringByAppendingFormat: @"%d/%d/%d.",
		month, day, year];

Other early examples of methods with a variable number of arguments will be the setWithObjects: method of class NSSet (see here), and the arrayWithObjects: method of class NSArray (see here).

Selectors

Here’s a typical use of a typical method of a typical object.

	[myObject myMethod: myArgument];

The name of a method can be stored in a string object. Remember that the colons are part of the name.

	//An NSString object can hold any string (sequence) of characters.
	NSString *string = @"myMethod:";
The name of a method can also be stored in a special type of variable called a selector. It holds the same information, but in a form that can be used for a special purpose, shown below.

	//A selector can hold only a string that is the name of a method.
	SEL sel = @selector(myMethod:);

To wait 10 seconds and then do [myObject myMethod: myArgument];, we can say the following. See Japan.

	SEL sel = @selector(myMethod:);
	[myObject performSelector: sel withObject: myArgument afterDelay: 10];

The two statements above can be telescoped to a single statement:

	[myObject performSelector: @selector(myMethod:)
		withObject: myArgument
		afterDelay: 10];

A selector in Objective-C does the same job as a “pointer to member function” in the language C++. We will pass a selector to

  1. the performSelector:withObject:afterDelay: method of class NSObject when we detect the difference between a single and double tap.
  2. the addTarget:action:forControlEvents: method of class UIControl (What message should the button send to which target object when the button is pressed?)
  3. the scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: method of class NSTimer
  4. the addObserver:selector:name:object: method of class NSNotificationCenter

Another way to pass a chunk of code to a method is as a block, often used with animations. See A Short Practical Guide to Blocks.

Nested parentheses

We have already seen parentheses in an expression. Here are nested parentheses:

	int result = ((1 + 2) * 3 + 4) * 5;	//The result is 65.
We can avoid the nesting, and even avoid the parentheses altogether, by introducing extra variables.
	int i = 1 + 2;
	int j = i * 3;
	int k = j + 4;
	int result = k * 5;

Nested square brackets

  1. The return value (s) we get back from one method might be the receiver to which the next message is sent.
    	UIScreen *s = [UIScreen mainScreen];
    	CGRect b = [s bounds];
    
    We can telescope this to
    	CGRect b = [[UIScreen mainScreen] bounds];
    
    with nested square brackets.

  2. The return value (b) we get back from one method might also be passed as an argument to the next method:
    	CGRect b = [s bounds];
    	[window initWithFrame: b];
    
    We can telescope this to
    	[window initWithFrame: [s bounds]];
    
    with nested square brackets.

  3. Combining both of the above examples,
    	UIScreen *s = [UIScreen mainScreen];
    	CGRect b = [s bounds];
    	[window initWithFrame: b];
    
    can be telescoped to a single statement:
    	[window initWithFrame: [[UIScreen mainScreen] bounds]];
    

Classes of Objects

The classes that have already been written for us begin with a pair of initials. Some example are

  1. NS (NeXTSTEP), e.g., NSAutoreleasePool, NSString.
  2. UI (User Interface), e.g. UIColor, UIFont, UIScreen, UIView, UIWindow.
  3. CG (Core Graphics)
  4. CL (Core Location)

Create an object by sending a message to a class

Most messages are sent to objects, but we can also send a message to a class. Think of the class as a factory that manufactures objects of that class. Let’s say we have a class named Point. (The name of a class begins with an uppercase letter; the name of a class invented by Apple begins with two uppercase letters. This class was obviously not created by Apple.) The alloc message tells the class to instantiate (create) a new object of that class. The new object is called an instantiation of the class. alloc returns the address of the instantiation (i.e., the address of the newborn object). We store the address in a pointer named point.

	Point *point = [Point alloc];

An object created by alloc does not become operational until we also send it the message init.

	Point *point = [Point alloc]; //Send a message to a class.
	[point init];                 //Send a message to an object.

Since init returns the address of the object to which it belongs, we can telescope these statements as follows.

	Point *point = [[Point alloc] init];
with nested square brackets. This is an example of the common idiom

	Classname *c = [[Classname alloc] init];

The init method that we just called to create a Point object takes no arguments. The init method that we call to create an object of another class might take several arguments; an example is the above initWithFrame.

	Point *point = [[Point alloc] init];
	Point1D *point1d = [[Point1D alloc] initWithX: 10];
	Point2D *point2d = [[Point2D alloc] initWithX: 10 y: 20];
	Point3D *point3d = [[Point3D alloc] initWithX: 10 y: 20 z: 30];

	CGRect frame = CGRectMake(0.0, 0.0, 320.0, 568.0);
	UIWindow *window = [[UIWindow alloc] initWithFrame: frame];

Other ways to create an object

Instantiating an object usually requires calls to two methods: the alloc method of a class, followed by the init method of the newborn object. For example, an object of class NSNumber holds one number.

	NSNumber *n = [[NSNumber alloc] initWithInt: 10];	//Instantiate a new NSNumber object.
	int i = [n intValue];					//Store 10 into i.

But some classes let us instantiate an object by calling a single method of the class. This method is referred to as a convenience constructor. Let’s instantiate the same object with a convenience constructor.

	NSNumber *n = [NSNumber numberWithInt: 10];	//Instantiate a new NSNumber object.
	int i = [n intValue];				//Store 10 into i.

Similarly, an object of class NSValue can hold one CGPoint structure.

	CGPoint p = CGPointMake(10.0, 20.0);
	NSValue *v = [NSValue valueWithCGPoint: p];	//Instantiate a new NSValue object.
	CGPoint q = [v CGPointValue];			//Store the point (10.0, 20.0) into q.

Was the object successfully created?

To make sure that a pointer does not point to any object, put the special value nil into the pointer. The following pointer is declared to be an id, so it could potentially point at any object of any class. But its initial value is nil, so it definitely does not point to any object.

	id p = nil;

The init method, its variants with arguments (such as initWithFrame:), and the convenience constructors return nil if they were unable to instantiate an object. If this is a real possibility, the conscientious programmer should follow each attempt at instantiation with an if statement.

	Point1D *point1d = [[Point1D alloc] initWithX: 10];

	if (point1d == nil) {		//two equal signs mean comparison
		NSLog(@"unable to create point1d");
	}
The above if is usually abbreviated

	if (!point1d) {			//Exclamation point means "not".
		NSLog(@"unable to create point1d");
	}

A check for a successful instantiation would look like this

	if (point1d != nil) {		//!= means not equals
		NSLog(@"was able to create point1d");
	}
and is usually abbreviated
	if (point1d) {
		NSLog(@"was able to create point1d");
	}

A singleton object

There is only one object of class UIScreen. This object exists eternally and is never created or destroyed, so we would never attempt to instantiate it. Instead, we can get the address of the one-and-only screen object by calling the method mainScreen of class UIScreen.

	UIScreen *screen = [UIScreen mainScreen];

Similarly, there is only one object of the following classes.

	UIApplication *application = [UIApplication sharedApplication];
	UIDevice *device = [UIDevice currentDevice];
	AVAudioSession *session = [AVAudioSession sharedInstance];
	UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];

Instance methods and class methods

A method that belongs to an object, and that is called when a message is sent to the object, is said to be an instance method of that object. Examples are the init method of every object, and the drawRect: method of every object of class UIView.

A method that belongs to a class, and that is called when a message is sent to the class, is said to be a class method of that class. Examples are the alloc method of every class, the mainScreen method of class UIScreen, and the convenience constructors such as the numberWithInt: method of class NSNumber.

When creating a method, we write a + in front of a class method and a - in front of an instance method.

Instance variables and properties

A big structure can contain little variables inside it, called the fields of the structure. Similarly, a big object can contain little variables inside it, called the instance variables of the object.

An instance variable of an object can usually be mentioned only by the methods of that object. That’s why we think of the instance variables as the “internal organs” of the object. An instance variable that can also be mentioned elsewhere is called a property of the object; the example we have seen is the bounds property of every object of class UIView. We will turn an instance variable into a property by creating a pair of methods that read and write the instance variable. The simplest way to create this pair of methods is with the @property and @synthesize statements.

Inheritance

Superclass and subclass

A class is the blueprint for a certain type of object. The class lists all the instance variables, properties, and methods that would belong to any object of this type. A class named Person, for example, might say that any object of type Person would contain a last name, first name, social security number, etc. The class would also say that any object of type Person has methods named hire, fire, etc. This would let us send the messages hire or fire to any object of this class.

It is possible to create a class from scratch. Usually, however, we build a class by starting with an existing class and adding extra instance variables, properties, and methods to it. Let’s start with the existing class NSString. An object of this class is capable of holding any string of characters: a word, several words, etc. Here’s an example:

	NSString *s = @"hello";
	NSLog("@s contains %@.", s);

The bigger and better class NSMutableString was built by starting with class NSString and adding extra instance variables, properties, and methods. Class NSMutableString has all the instance variables, properties, and methods that class NSString has, plus more. This means that an object of class NSMutableString has all the instance variables, properties, and methods of an object of class NSString, plus more. The additional functionality delivered by an NSMutableString object is the ability to change the string that is stored in the object. Every NSMutableString is a NSString, but not every NSString is a NSMutableString.

We say that class NSString is the superclass and class NSMutableString is the subclass, and that the subclass is derived from the superclass. The documentation for each class always tells who the superclass is for that class, if there is a superclass. In a diagram showing the relationship between classes, the superclass is always drawn above its subclass(es).

Class NSString in turn was derived from class NSObject, so class NSMutableString is really a grandchild. All the classes belong to one big family.

The above diagram showed the relationship between three classes. Now let’s show where the objects of each class are located in memory. An object of class NSMutableString contains an object of class NSString inside of it. The NSString object is called the superclass object of the NSMutableString object. (The NSMutableString object will humbly refer to itself as “self”, and will respectfully refer to the NSString object inside it as “super”. Those of you who read that notorious self-help book for men, Robert Bly’s Iron John, with its instructions for drumming in the forest and getting in touch with your “inner warrior”, will find this territory familiar.)

The innermost object is always created first, then the middle object, and then the outer object. (If the outer object was created first, then for a brief period it would be hollow. But we never want to have a hollow object: it could not survive for even a millisecond with no internal organs.) Conversely, when the whole thing is torn down, the outermost object is destroyed first, then the middle object, and then the inner one.

Accountants call this sequence “LIFO”: last in, first out. The rest of us call it “last hired, first fired”. Now let’s translate it into Objective-C. The act that brings an object to life is the call to its init method. Memorize the following incantations.

  The init method of the subclass always begins by calling the init method of the superclass.
The dealloc method of the subclass always ends by calling the dealloc method of the superclass.
 

Examples of inheritance

There are many examples of inheritance, all starting with class NSObject. Inheritance allows software to be built in layers.

NSObject
NSString        (has everything an NSObject has, plus the ability to hold a string)
NSMutableString (has everything an NSString has, plus the ability to change the string)
NSObject
NSArray
NSMutableArray
NSObject
NSSet
NSMutableSet
NSObject
NSDictionary
NSMutableDictionary
NSObject
UIResponder (has everything an NSObject has, plus the ability to respond to touches and G-forces)
UIView      (has everything a UIResponder has, plus the ability to appear on the screen)
UIWindow    (has everything a UIView has, plus the ability to be the root view)
NSObject
Shape       (the textbook example)
Square, Triangle, Circle, etc.: a class can have more than one subclass
NSObject
Amniote     (has an amnion)
Synapsid    (has everything an Amniote has, plus a synapsid opening)
Mammal      (has everything a Synapsid has, plus those 3 little bones in the middle ear)
Placental   (has everything a Mammal has, plus a placenta)

Protocols

A class can inherit more than just instance variables, properties, and methods. It can also inherit protocols. A protocol is a set of obligations. Class HelloAppDelegate in the Hello app, for example, will be derived from NSObject <UIApplicationDelegate>. This means that HelloAppDelegate inherits the instance variables, properties, and methods of NSObject, and also inherits the set of obligations named UIApplicationDelegate.

One of the obligations imposed by UIApplicationDelegate is to have a method named application:didFinishLaunchingWithOptions: (or applicationDidFinishLaunching: in older versions of the SDK). This method is the first method of the application delegate to be called (or at least the first method that we can see being called). The last method is applicationWillTerminate:.

An Objective-C protocol is similar to a Java “interface”.