Objective-C Lesson 5: Loops


A computer is really good at executing the same thing over and over again. A lot of programming involves doing the same thing over and over again (and no, that’s not meant to be a programming joke, although it could certainly be taken as one). Objective-C allows for two main ways of looping. We’ll start with a rather general problem.

The for() Loop

The Problem

Create a program that displays the sum of all the numbers from 1 to a user-specified value. Note that to get a user-specified value, we are going to be using a function call to scanf(), which is similar to NSLog, except that it reads input, rather than exporting it. A brief explanation will follow, but scanf() is not a function that you will regularly use on the iPhone. It is just a “place-holder” way to get input until we can use better options.

As for the problem itself, we are adding all the numbers between 1 and the input. So if the input was 5, we would output the sum as 1 + 2 + 3 + 4 + 5, or 15.

The (Inefficient) Solution

We could just take all the values and simply add them up:

int sum = 1 + 2 + 3 + 4 + 5;

sum would equal 15, just as expected. But although this method is rather simple and the most logical at this point, it is not very efficient, or scalable. If the user had entered a large value, such as 1000, writing the code for that would be torturous. But there will be a user who will enter 1000. You will almost never be able to anticipate every single type of input your user might give or do to your program, and you should probably have a solution to handle every case. So how are we going to handle the case of the user inputting 1000—or indeed, any value other than 5 (in this case)?

The Best Solution

We would use a loop. Here is the code to accomplish the problem above, using a for() loop:

#import <Foundation/Foundation.h>int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	int sum = 0;	// Make sure we start at zero, to avoid issues later

	// Allow user input
	NSLog(@"Please enter a value.");
	int times;
	scanf("%d", &times);

	// for() loop construct:
	for(int n = 1; n <= times; n = n + 1)
		sum = sum + n;

	NSLog(@"Sum of all values from 1 to %d is %d", times, sum);

    [pool drain];
    return 0;
}

The output shows that for an initial value of 1000, the sum is 500500.

Code Demystified

The for() loop is basically three statements in one line. Within the parentheses following the “for”, you have the initial expression, condition, and the loop expression. These are separated by semicolons.

Initial Expression

This statement is usually used to initialize variables used in the loop and assign them values. Usually this will be a counter of some sort which will not be used elsewhere in the program. In this case, I like to declare the variable and assign it a value at the same time, as I did above, rather than having int n; and then n = 1; in the loop. It just makes the code more concise.

You can initialize and declare more than one variable at a time: int a = 0, b = 3, c = 5;. For the most part though, you will only need some form of a (integer) counter variable, and you won’t need multiple variables. You could still use that to your advantage, though.

It is important to note that any variables you initialize here (initialize means that you have not made any mention of this variable before, and you are creating a new variable here) are only valid within the loop—as soon as you exit the loop (described below) the variable is no longer accessible.

Condition

This is a boolean condition that determines if the loop is still valid. If this expression becomes untrue (usually due to the loop expression), then the program exits out of the loop without running through the loop again. The program then moves on to the next line after the loop.

Remember that when comparing integers, as you usually will when using a loop, the following two expressions are equivalent: n <= 1000; and n < 1001;. But in this case, because you are only checking up to 1000 (and because the user entered 1000, and you should avoid modifying the input if possible; in addition, having to add one to the input just to use a less-than construct is not a good choice), the first expression makes more logical sense.

Loop Expression

This is an expression that is executed after the main body of the loop; it is usually a way to increment the initialized variable(s). In this case, the counter variable n is incremented by 1, so that eventually the loop condition will become false.

General Operational Procedure

Excerpted from Stephen Kochan’s Programming in Objective-C 2.0, 2nd Edition published by Addison-Wesley, &copy2009:

  1. The initial expression is evaluated first. This expression usually sets a variable that is used inside the loop, generally referred to as an index or counter variable, to some initial value (often 0 or 1).
  2. The looping condition is evaluated. If the condition is not satisfied (the expression is FALSE or NO), the loop immediately terminates. Execution continues with the program statement that immediately follows the loop.
  3. The program statement(s) that constitutes the body of the loop is executed.
  4. The looping expression is evaluated. This expression is generally used to change the value of the index variable, frequently by adding or subtracting 1.
  5. Return to step 2.

The while() Loop

This is another type of loop that Objective-C supports. Although most tutorials and textbooks would consider them (roughly) equivalent, I use for() loops whenever I know how many times I want to go through, whether it is by a hard-coded value or by a the value in a variable. The while() loop is better suited for cases where the program does not know how many times it is to be run, and instead checks for a different condition. This can be better illustrated with an example.

The Problem (Revised)

Calculate the sum of all the integers that the user enters; the user input is terminated by any negative value.

The Solution

This would be very difficult to do with a for() loop, as you do not know how many times to execute. You would have to do an ugly check in the loop condition. A while() loop makes this more elegant.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	NSLog(@"Input a list of integers. Hit Return after each one. End the list with a negative value.");
	int sum = 0;
	int input = 0;
	scanf("%d", &input);

	while (input >= 0) {	// "Greater-than or equal to zero" is the same as "not negative"
		sum = sum + input;
		scanf("%d", &input);
	}

	NSLog(@"The sum of all those values is %d", sum);    [pool drain];
    return 0;
}

Here is a sample run:

Input a list of integers. Hit Return after each one. End the list with a negative value.
5
2
18
30
37
69
-29
The sum of all those values is 161

Code Demystified

The expression for the while() loop is a simple boolean condition (the middle part of the for() loop). This gets evaluated, and if it is true, the body is executed. If not, the program moves on. This means that in the loop, you have to make the value untrue somehow; otherwise you will get an infinite loop.

The do-while Loop

In a regular for() or while() loop, the condition is checked first, then the loop is executed. This means that if the initial condition was false to begin with, the body of the loop would never ever get executed; the code would skip directly over the loop. The do-while loop is guaranteed to perform one iteration of the loop first, before checking the condition. From that point on, as long as the condition remains true, the loop will continue to execute. The syntax is as follows:

int n = 1;
do {
	sum = sum + n;
	n = n + 1;
} while (n <= 5);

The above example is a re-writing of the previous loop examples, using the do-while construct. A more compelling example might look like this:

int sum = 0;
int input = 0;
do {
	sum = sum + input;
	NSLog(@"Sum is %d", sum);
	scanf("%d", &input);
} while (input != -1);

In the above example, the program will continue to display the sum of all the values the user enters until negative 1 is entered. The loop in this case ensures that the NSLog is printed at least once, and the user input is gathered; in this case, the input is placed in the loop, rather than having to have an additional scanf() outside of the loop. This makes the code a little easier to read and understand.

Pitfalls

A few things that people get tripped up on:

  • Forgetting braces: If you have more than one statement that you want to execute given a certain condition, you must enclose them within curly braces. Otherwise, they can stand alone as one line, without braces.
  • The Infinite Loop: The loop condition must be made false, somehow. (It’s also a really good idea to actually have a loop condition). Otherwise, your loop will never end, and it keep running until your computer crashes, or until the power goes out.

Conclusion

Loops are relatively easy to implement, yet they can save you a lot of coding. For a big loop, like in the first example, you truly begin to leverage your computer’s processing power, and save yourself a lot of work. When combined with if() statements, they can become quite powerful.

Extension 5: The switch Statement


The switch() statement is used in place of a chain of if()else if()else if()else if()else construct, where such a chain does not lead to very readable, follow-able code. The switch() statement is designed for this situation. Here is the general format:

switch(expression or variable)
{
     case value1:
          // Program statement
          // Program statement
          ...
          break;
     case value2:
          // Program statement
          // Program statement
          ...
          break;
     case value3:
          // Program statement
          // Program statement
          ...
          break;
     ...
     case valueN:
          // Program statement
          // Program statement
          ...
          break;
     default:
          // Program statement
          // Program statement
          ...
          break;
}

The expression value in the parentheses at the beginning of the statement is compared to each of the values, and when one of them matches, the following code (note the colon, and the lack of braces around each case), the code below is executed. It then breaks out of the rest of the switch, to avoid executing the rest of it (“overflowing” into the code for the next condition). This can sometimes be used intentionally, but for most of the time make sure to use the break; statement.

If none of the conditions match (the else of an if()else block), the code under the default condition is executed.

The following is an example of a switch() statement and the equivalent if()else block:

// This is an example of a switch statement.
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	NSString *operator = [[NSString alloc] init];     // We will talk in depth about NSString later on down the road.
	// Assume operator has been initialized to a valid value
	// Valid values for operator are @"+", @"-", @"*", and @"/"

	switch (operator) {
		case @"+":
			NSLog(@"Operator is for addition.");
			break;
		case @"-":
			NSLog(@"Operator is for subtraction.");
			break;
		case @"*":
			NSLog(@"Operator is for multiplication.");
			break;
		case @"/":
			NSLog(@"Operator is for division.");
			break;
		default:
			NSLog(@"Unknown operator.");
			break;
	}

    [pool drain];
    return 0;
}

This code should be rather self-explanatory; operator is compared to the values after each case, and if one of them matches, the executes the corresponding NSLog and breaks out of the switch. If none of them match, then it hits the default statement.

The equivalent if()else block follows:

// This is an example of a switch statement.
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	NSString *operator = [[NSString alloc] init];
	// Assume operator has been initialized to a valid value
	// Valid values for operator are @"+", @"-", @"*", and @"/"

	/* Note that NSString actually has a comparison method, and that
	   this method of comparison is not guaranteed to work. We are
	   overlooking that at the moment for the sake of education. */
	if (operator == @"+")
		NSLog(@"Operator is for addition.");
	else if (operator == @"-")
		NSLog(@"Operator is for subtraction.");
	else if (operator == @"*")
		NSLog(@"Operator is for multiplication.");
	else if (operator == @"/")
		NSLog(@"Operator is for division.");
	else
		NSLog(@"Unknown operator.");    [pool drain];
    return 0;
}

This code does the same thing as the switch statement above (bar the comment in bold).

The switch() statement is makes more logical sense, but some people find it annoying. It all comes down to a matter of personal preference. No big deal.

BTW less than a month after the previous milestone we are at 2000 views! Thanks to everyone who stopped by, and I hope to see you back!

Postscript: Wikipedia has a nice article on controlling program flow. It is a bit dense, but for anyone who is interested, go check it out! And while you’re there, you might as well see the article on the switch statement as well.

Objective-C Lesson 4: if() statements and Booleans


As mentioned before, boolean values are simply true-or-false. In Objective-C, unlike many other languages, they are represented as YES or NO:

BOOL trueOrFalse = YES;
BOOL gameOver = NO;

Internally, however, they are stored as zero and one.

if() Statements

The if() statement is used to check for conditions. Just like we use if in normal English, if() in code is used to test for a condition—they test for the value of a boolean (or any int—in this case, a zero is considered false; any non-zero value is true).

Here is a simple example of booleans:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	BOOL trueOrFalse = YES;
	if (trueOrFalse)
		NSLog(@"trueOrFalse is true.");
	if (1)
		NSLog(@"1 is considered to be true.");
    [pool drain];
    return 0;
}

The output is:

trueOrFalse is true.
1 is considered to be true.

Simple enough, and quite logical.

Obviously, if the condition was false, the statements following would not be executed. The following example demonstrates:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	BOOL trueOrFalse = YES;
	if (trueOrFalse)
		NSLog(@"trueOrFalse is true.");
	if (1)
		NSLog(@"1 is considered to be true.");	// If false, statement following is not executed
	trueOrFalse = NO;
	if (trueOrFalse)
		NSLog(@"I lied. trueOrFalse is not true.");
	if (0)
		NSLog(@"This line should not appear.");
    [pool drain];
    return 0;
}

Unsurprisingly, the results are the same as above.

One important point to make here: if you only have one statement after the if(), you can just leave it like it is above. But if you have more than one statement after the if(), you must enclose them within braces:

if (trueOrFalse) {
	NSLog(@"trueOrFalse is true.");
	NSLog(@"This second line must be within the braces.");
}

Otherwise, the second (or additional) statements will be executed, regardless of if the condition was true or not.

Extending the if() Statement

In real life though, there are often alternatives: if something is true, do “action1“; else, do “action2“. Objective-C lets you model that quite simply:

trueOrFalse = YES;
if (trueOrFalse == YES)          // The double-equals sign is a comparison; versus a single equals, which is an assignment. More on this in the next Extension.
	NSLog(@"If true, print this");     // This gets printed
else
	NSLog(@"Else, print this");        // This does not get printed
trueOrFalse = NO;
if (trueOrFalse)
	NSLog(@"If true, print this");    // This does not get printed
else
	NSLog(@"Else, print this");       // This gets printed
 

Output is:

If true, print this
Else, print this

This makes logical sense.

You can also extend this by using else if(). This is easier to explain with code:

int value = 5;
	if (value > 0)
		NSLog(@"value is greater than zero.");
	else if (value == 0)
		NSLog(@"value is equal to zero.");
	else
		NSLog(@"value is less than zero.");

Output is:

value is greater than zero.

You can have as many else if()s as you want; they simply follow each other:

int value = 5;
if (value == 6)
	NSLog(@"value is equal to 6.");
else if (value == 0)
	NSLog(@"value is equal to 0.");
else if (value == 2)
	NSLog(@"value is equal to 2.");
else if (value == 10)
	NSLog(@"value is equal to 10.");
else
	NSLog(@"value does not equal 6, 0, 2, or 10");     // This line is the output.

Pitfalls

There are a few issues that may arise with if()statements.

  • Forgetting braces: If you have more than one statement that you want to execute given a certain condition, you must enclose them within curly braces.
  • Using too many instances of if(): If you want to have a collection of related paths (if…else if…else), you must remember to use else if(). Using a chain of if()s is a completely different thing, logically. Think about it.
  • Forgetting the last else: The final else is a “catchall” statement that is executed if none of the previous if() or else if() statements are true. Don’t forget the else; otherwise, you may never get any output. For example, in the last code example, the last else statement was needed; otherwise, it might have appeared that the code was broken.

Conclusion

As you can see, the if() statement is quite simple, but very powerful—it defines “paths” down which your code can travel, based on the value of a condition. In the next Extension, we will be looking at what these conditions can be.

Extension 2: Floating-Point Operations


Not all numbers are integers. Therefore, Objective-C lets you define floating-point values—numbers with a fractional portion. There are two basic types—float and double.

Floating-point values do not follow the rules of integer division—that is, dividing by floating-point values produces floating-point results.

Type float

In certain programming languages (Java comes to mind) the float type is almost never used. In Objective-C, it is the more commonly used of the two—both for practical and memory reasons.

A floating point number must contain a decimal portion, but you can omit digits before or after the decimal point—obviously, not both. The entire number ca be prefixed by a negative sign. Therefore, 3., 1.8, .295, and -.59 are all valid floating point numbers. To display floats in an NSLog call, use %f.

Scientific Notation

As you may recall from a high-school math class, scientific notation is a method of writing absurdly large or small numbers. It takes the form 5.925×102, where the general notation is of a floating-point value followed by a multiplication, a number (generally a power of 10), and an exponent. This number is written in code with the form 5.925e4. The e, formally known as the mantissa, can be written as a capital or lowercase. The mantissa can be either positive or negative; a negative value, such as 2.25e-3, would correspond to a value of 2.25×10-3, or 0.00225.

To display scientific notation, use %e. Alternatively, you can use %g to have NSLog decide whether to display the usual value or the scientific notation—if the exponent is less than -4 or greater than 5, the scientific notation is used; otherwise, the standard floating point notation is used.

Type double

A double value is a more precise float value—the former stores twice as many digits, and on most systems it uses 64 bits.

Like Java, all floating point constants in Objective-C are double. To force a float, append either f or F to the end of the floating point value. Unlike Java, however, floats are used as a general data type for floating-point variables, due to the fact that they require less memory. The distinction is that of constants versus that of variables.

The same format specifiers apply to doubles, as well as scientific notation.

Objective-C Lesson 3: Object-Oriented Programming


When object-oriented programming arrived in the programming world, it was considered a savior of software by some and yet another foolish experiment by others. Regardless of the perspective, we need to define some basic concepts and terminology before we begin

A Thing

An object is a thing. In the real world, you have “things,” all of which have certain properties. For example, you probably have a car—a “thing.” The car has properties, such as paint color, total mileage, make, model, and year. You can also do things with the car, or have something done to it—for example, you can drive twenty miles in the car, or wash the car.

In an object-oriented program, your specific car is an instance of a class, generally called Car. A class is the definition of the object, and in most cases can be thought of as a “factory” for its instances. A class can create many instances of the same type of object, although they have to have different names. An object is simply a variable, but it can be (and usually is) of a custom type.

Instance Variables and Methods

As mentioned before, your car, and any other car, has certain properties that are potentially unique to that specific instance. These properties are known as instance variables, or ivars for short. Instance variables are variables, of either the standard data types, or of any other object, but they are private to the object—that is, every single instance of Car has its own identical set of instance variables; although the variables may be of the same type and number, they can (and usually do) contain different values across different instances.

A method is the proper term for a function, or simply a piece of code that is called upon to perform some action. In Objective-C, there are two types of methods—class methods and instance methods. Class methods are performed directly on the class that an object belongs to—for example, a class methods might ask the car factory how many cars it produced the previous year. Instance methods are performed on specific instances of a class—for example, you might ask one specific car to drive twenty miles, or you might wash one specific car; you wouldn’t do those things to the entire factory. Instance methods affect the state or condition of the object. Just like two identical cars adopt different characteristics over their lifetime, different instances of Car can take on different traits as well.

Message Objects

In Objective-C, there is a specific syntax for calling methods:

[ClassOrInstance method];

The method call begins with an open bracket. This is followed by the name of the class or instance, depending on whether the method belongs to a class or instance. This is followed by a space, and then the name of the method. This is followed by a closing bracket, and the all-important semicolon.
In more formal terminology, the following message call might be described as

[receiver message];

The meaning is the same.

Sample Program

Now, with the theory cleared up, we can move on to our first program involving classes.

Program 3.1

// A simple implementation of a Fraction
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

	int numerator = 2;
	int denominator = 5;
	NSLog(@"This is a fraction with a value of %d/%d", numerator, denominator);

	[pool drain];
	return 0;
}

The output is

This is a fraction with a value of 2/5

In Program 3.1, we defined a numerator and denominator variable, and set them to integer values. We then printed the result of this simple fraction.

This program is short and condensed, and seems to be pretty simple—and it is. But what if we had a hundred fractions that we wanted to store? We’d have to keep track of two hundred variables. And performing operations on those variables would not be any easier.

As a matter of fact, Program 3.1 is not a true object-oriented program. It is still written using C-style code. We have not created any objects in the code; our Fraction object still exists only psychologically.

Program 3.2 presents the exact same functionality, except that we actually define this object in code. We then refer to the object as Fraction throughout the program. Don’t worry if it looks daunting; an explanation follows.

Program 3.2

// A Fraction class
#import <Foundation/Foundation.h>

//———————— Interface ————————

@interface Fraction : NSObject
{
	int numerator;
	int denominator;
}

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

@end

//———————— Implementation ————————

@implementation Fraction

- (void)showResults {
	NSLog(@"This is a fraction with a value of %d/%d", numerator, denominator);
}

- (void)setNumerator:(int)n {
	numerator = n;
}

- (void)setDenominator:(int)d {
	denominator = d;
}

@end

//———————— Main Program ————————

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Create an instance of Fraction
	Fraction *myFraction;

	myFraction = [[Fraction alloc] init];

	// Set myFraction to 2/5
	[myFraction setNumerator:2];
	[myFraction setDenominator:5];

	// Display the value of myFraction
	[myFraction showResults];

	// Clear up memory
	[myFraction release];

    [pool drain];
    return 0;
}

The output is

This is a fraction with a value of 2/5

Code, Demystified

Program 3.2 is divided into three logical sections. These are known as the interface, implementation, and program section, respectively.

The interface section (delineated by @interface in the code) provides basic program-wide definitions, the implementation section (delineated by @implementation) provides the implementation of the methods, and the program section contains the main code that does something.

The @interface Section

Every class in Objective-C has a single parent, or superclass, from which the class inherits. Next, you have to declare the instance variables that belong to the class. Finally, you declare the methods, or actions, that the class can perform. This is all done in the @interface section, which looks like this:

@interface ClassName : ParentClassName
{
	instanceVariableDeclarations;
}
methodDeclarations
@end

Remember that the compiler ignores spaces, so you may put line breaks and spaces anywhere within the code above.
By convention, the name of a class begins with a capital letter, as in the Fraction class.

You can tell that our Fraction class is a subclass of NSObject, which is the root object that almost everything else inherits from, directly or indirectly. NSObject is declared in the Foundation files which you imported.

Fraction contains two instance variables; both are ints. They are called instance variables because every instance of Fraction creates a new set of these variables, unique to that specific instance. So, FractionA’s numerator is a different variable than FractionB’s numerator. Objective-C automatically keeps track of this for you.

Currently, our Fraction class declares (and later implements) three methods. All are instance methods, as noted by the minus sign () preceding each method name. A class method is delineated by a plus sign (+).

Before we discuss the method declaration, we must remember than an object is considered a “black box.” Ideally, objects encapsulate, or hide, their instance variables, from anything except itself. The object exists as a single entity, and anything that works with the object does not need to know, and should not know, about the object’s inner workings. Therefore, we need to declare specific methods to set the variables, because the program should not directly manipulate them. We also need a separate method to print the values, because, once again, the program should not be able to directly access the variables. This is a fundamental concept in Objective-C, and is observed throughout the libraries and code.

The Fraction class defines three methods, all of which return nothing. The value in parentheses before the method name specifies the return type of the method. void is programming parlance for “nothing,” or nil. Any data type or object can be a return value; a method might return a float, int, or another Fraction, as illustrated by the following methods:

- (int)numerator;
- (float)divide;
- (Fraction *)randomFraction;

The asterisk after the Fraction is used to delineate a pointer; this is not an important concept at the moment. For now, simply remember that anytime you create an instance of a custom object, the name of the instance should be prefixed with an asterisk.

All of these methods must return a value somewhere in the method. Just as main returns 0 at the end, these methods must return an int value, a float value, and another instance of Fraction, respectively. The compiler will complain if you do not return a value.

The latter two methods declared in Fraction return no value, but they do each take an integer value as an argument. In the case of setNumerator:, the name of the argument is n. This name is arbitrary, as long as it follows the standard naming conventions, and is used only within the method to refer to the argument. The argument itself exists only within the method; you cannot access n anywhere else in Fraction.

Arguments are values that are passed into a method, which the method would not be able to obtain otherwise. For example, setNumerator: requires a value to set to the numerator, but it would not receive a custom value without an argument.

Note the syntax of these method declarations. The method name begins with the minus or plus, signifying the method type. This is followed by the return type in parentheses, the name of the method, and a colon. This colon is followed by an argument type in parentheses, a name for the argument, and a semicolon. In a method that takes an argument, the colon is considered part of the method name.

A method can take multiple arguments; they are delineated by a space, a new section of the method name, another colon, an argument type, and name. This will be covered in a later chapter.

The @implementation Section

In the implementation section, you define the code that each method implements. The general appearance of the @implementation section is similar to this:

@implementation ClassName
	methodDefinitions;
@end

In the implementation of Fraction, you also declare the method types and names, followed by an open brace. Between the opening and closing brace, you insert the code that the method will execute when it is called.

The program Section

In this program, the main program section contains the all-important main function that is the first thing to be executed.

In Program 3.2, we first create an instance of Fraction:

 Fraction *myFraction;

Again, don’t worry about the asterisk. From a technical perspective, it says that myFraction is a pointer to a Fraction.

Now that you’ve created an object “container” to store a Fraction, you have to actually create a Fraction to fill that space. You do that in the next line,

myFraction = [[Fraction alloc] init];

In this line, you call the alloc method on Fraction; alloc is a class method. Although you never defined the alloc method, it is inherited from NSObject. Inheritance will be discussed in a later lesson.

After you allocate a Fraction, you have to actually initialize it. Therefore, you pass the value of the alloc method to NSObject’s init method, and the resulting Fraction is assigned to myFraction. This nested sequence of messages is used almost every time you create a new object.

Next, you set the values of myFraction to 2 and 5 by using the proper method calls.

[myFraction setNumerator:2];
[myFraction setDenominator:5];

You pass the integers 2 and 5 as arguments to the method. The method then takes these arguments and sets the numerator and denominator variables of myFraction.

You then call myFraction’s showResults method to print the value of the fraction.

We then free up the memory that Fraction uses by calling the release method:

[myFraction release];

This is a critical part of programming for iOS. Whenever you create a new object through alloc/init, you have to release it—in other words, every alloc/init call is balanced by a release call. Otherwise, the now-useless object will still sit in memory, taking up space; in a memory-constrained environment such as the iPhone, you want to use as little memory as you can.

Messaging Receivers

In every message, you send the message to a specific receiver—the object or class which implements the method. However, instance methods are sent to specific instances, so that the same method call to two different Fractions will result in two Fractions with potentially different values. For example,

[fraction1 setNumerator:2];
[fraction1 setDenominator:5];

[fraction2 setNumerator:3];
[fraction2 setDenominator:4];

Will result in two separate fractions, one with a value of 2/5 and another with a value of 3/4. Although you are calling the same methods on both, they are received by different objects, with their own set of numerator and denominator variables.

Data Encapsulation

As mentioned before, you shouldn’t directly access the instance variables of an object. Data encapsulation provides some security against people working with the class, to prevent them from tinkering with the inner workings. So in the main function, how would you access these values?

Generally, you access these values by writing special methods, known as getter methods (the set methods that we’ve already wrote for Fraction are known as setter methods; they are generally written in pairs).

The getter methods for the Fraction class look something like this:

- (int)numerator;
- (int)denominator;

- (int)numerator {
	return numerator;
}
- (int)denominator {
	return denominator;
}

It doesn’t matter if the method name is the same as the variable name; in fact, it is common practice.

Program 3.3 contains the main function that tests these new methods.

Program 3.3

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Create an instance of Fraction
	Fraction *myFraction;

	myFraction = [[Fraction alloc] init];

	// Set myFraction to 2/5
	[myFraction setNumerator:2];
	[myFraction setDenominator:5];

	// Display the value of myFraction
	NSLog (@"The value of myFraction is %d/%d", [myFraction numerator], [myFraction denominator]);

	// Clear up memory
	[myFraction release];    [pool drain];
    return 0;
}

The output is

The value of myFraction is 2/5

Objective-C 2.0 introduces properties, which provide an easy way to create getter and setter methods. This will also be covered in a later lesson.

Shameless Self-Promotion


To get the word out, I’d generally rely on search engines. And I can’t afford to pay Google to get listed (and most of those ads aren’t exactly reputable anyway). So, here’s some shameless self promotion. I promise I won’t really do this much more. Feel free to not read this. You may want to entertain yourself elsewhere (I’d recommend Uncyclopedia).


Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa Cups of Cocoa

iPhone App Development iPhone App Development iPhone App Development iPhone App Development

iPhone Application Development iPhone Application Development iPhone Application Development

Programming for iOS Programming for iOS Programming for iOS Programming for iOS Programming for iOS

iPhone App iPhone App iPhone App iPhone App iPhone App iPhone App iPhone App iPhone App iPhone App

iPhone Apps iPhone Apps iPhone Apps iPhone Apps iPhone Apps iPhone Apps iPhone Apps iPhone Apps

Creating iPhone Apps Creating iPhone Apps Creating iPhone Apps Creating iPhone Apps Creating iPhone Apps

iPhone Programming iPhone Programming iPhone Programming iPhone Programming iPhone Programming iPhone Programming

Developer Developer Developer Developer Developer Developer Developer Developer Developer Developer Developer

iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS iOS

App Store App Store App Store App Store App Store App Store App Store App Store App Store App Store App Store

Programming Programming Programming Programming Programming Programming Programming

iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone iPhone

iPod Touch iPod Touch iPod Touch iPod Touch iPod Touch iPod Touch iPod Touch iPod Touch

iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad iPad

Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode Xcode

Objective-C Objective-C Objective-C Objective-C Objective-C Objective-C Objective-C Objective-C

Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple Apple

Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa Cocoa

iPhone SDK iPhone SDK iPhone SDK iPhone SDK iPhone SDK iPhone SDK iPhone SDK iPhone SDK

Software Software Software Software Software Software Software Software Software Software Software

Object-Oriented Programming Object-Oriented Programming Object-Oriented Programming Object-Oriented Programming


😀

Objective-C Lesson 2: Basic Variables


In almost all programs, values may change; these values are stored in variables, which, as the name implies, are designed to have varying contents as the program is used. We’ll dive right in with a sample program.

Program 2.1

// Introducing variables

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	int i;
	i = 1;
	NSLog (@"The variable i has a value of %d", i);

	i = 2;
	NSLog (@"The variable i now has a value of %d", i);

    [pool drain];
    return 0;
}

The output of this simple program is as follows:

The variable i has a value of 1
The variable i has a value of 2

Code, Demystified

Program 2.1 contains the same “boilerplate” code in the template that Xcode provides for you. It is still not necessary for now, so explanation will be deferred.
The first “real” line of the program introduces the concept of a variable.

int i;

This variable is declared to be of type int and with the name i. Before we talk about the variable type, we have to take about the choice of the variable’s name.

Variable Names

In C, all variable names (in fact, almost all names in general) must be made of lowercase and uppercase letters, digits, and the underscore character (_). The first character of the name must be a letter or underscore. Because Objective-C is a strict superset of C, the same rules apply.

Note that C and Objective-C are case-sensitive. A lowercase letter is not the same as a capital letter. Therefore, fraction, Fraction, FRACTION, and fractioN are considered four completely different names. As a result, programmers often use camel case to declare variable names of multiple words. Examples include aPairOfDice, lotsOfMoney, and someAddress.

Because of the wide variety of options available to you, make sure to choose descriptive variable names, such as taxRate instead of t. You can only thank yourself later on.

Reserved Names

The Objective-C language reservescertain words, so that you cannot use them as a name; in fact, some are reserved by C itself. For a complete list, check out this post.

Data Types

In program 2.1, the variable i was declared to be of type int. This means that i can only hold a whole-number value, without a decimal point—an integer. Integer values are one of four basic data types. The others are floating-point values, characters, and boolean values. Floating-point values are simply numbers that include a fractional portion, represented as a decimal, such as 5.2 and 10.0. Characters are any single character that you can type on your keyboard, such as ‘A’ and ‘@’ and few others. Boolean values are either true or false; in Objective-C they represented as YES and NO.

Beyond the basics, C also defines three “adjectives” to modify the size of variables. These are short, long, and unsigned. An integer declared to be short will take up less memory than a standard int, and a long will take up more space. You can also use the specifier long long to indicate even larger values, but in OS X and iOS the additional long makes no difference. unsigned is used for values that will never be negative; this effectively doubles the maximum (positive) value of a variable without doubling its storage requirement (because every single negative value can now be “mapped” to a larger positive value).

short and long cannot be used in conjunction with each other in the same variable, but unsigned, or its optional counterpart signed, may be used on any variable, short, regular, or long.

Initialization

After declaring a variable, you have to initialize it with a value; otherwise, the variable would be useless. You can do this in a single statement, along with the declaration:

int variable = 1;

Alternatively, you can declare the variable, and then initialize it sometime later (it does not have to be the next statement):

int variable;
// Some code
variable = 1;

Printing Variables

Program 2.1 introduces a few new concepts in the NSLog statements.

NSLog (@"The variable i has a value of %d", i);

The real magic happens with the %d. This is a format specifier, and tells NSLog that it should expect a variable of a certain data type, and to print the value of that variable. In this case, the type %d tells NSLog to expect an integer value, and it does receive i as an argument, which is an integer value. Therefore, NSLog looks for the value of i, and prints the integer value. This explains the output:

The variable i has a value of 1

In the next few lines, we set i to the value 2, and then use NSLog to print it.

Note that the specifier %i is also used to print integer values.

Program 2.2

// Arithmetic operations with variables
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    int result;
	result = 10 + 20;
	NSLog(@"The sum of 10 and 20 is %i", result);

	result = 25 - 30;
	NSLog(@"The difference between 25 and 30 is %i", result);

	result = 8 * 9;
	NSLog(@"The product of 8 and 9 is %i", result);

	NSLog(@"The quotient of 8 and 5 is %i", (8 / 5));
	NSLog(@"The quotient of 8.0 and 5.0 is %.1f", (8.0 / 5.0));	[pool drain];
    return 0;
}

The output is:

The sum of 10 and 20 is 30
The difference between 25 and 30 is -5
The product of 8 and 9 is 72
The quotient of 8 and 5 is 1
The quotient of 8.0 and 5.0 is 1.6

Program 2.2 presents some interesting situations. To begin, we define an integer value, and name it result. We set result equal to 10 + 20. Then we have the NSLog statement print out the value of the variable result, and we use the integer specifier because the result is an integer. The next few lines does the same, but note that negative values are supported. Multiplication works as expected, but the last two NSLogs deserve some attention.

The first thing to note is that you can specify an expression as an argument to NSLog, not simply a variable. As long as the result is of the proper type, NSLog doesn’t care whether you specify an expression or a variable.

Next, note that the first division results in a value of 1. Obviously, 8 ÷ 5 ≠ 1, but this is not a mathematical error. Remember that the format specifier %i is responsible for printing integers. Also note that the values 8 and 5 are both integers. This is an example of integer division. Through integer division, only the whole-number portion of the result is reported—any fractional portions are discarded.

To get the accurate result, we have to use floating-point numbers. These numbers are only syntactically different from ints in that they include a .0 portion at the end—as in 8.0 and 5.0. To print a floating-point value, we use the format specifier %f. The .1 portion of the specifier tells NSLog to only print the first decimal point, and disregard any others that may follow. Here, we can see that the result is indeed 1.6.

Objective-C Lesson 1: Hello World!


Note: Click on any image to see a larger version.

Since Dennis Ritchie demoed the C programming language, it has been conventional to begin a programming course with a program that writes the words “Hello world!” to the computer screen. Diving right in, the code is shown below.

Program 1.1

// First program example

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSLog (@"Hello, World!");
        [pool drain];
        return 0;
}

Using Xcode

So what does all this gibberish mean? Before we can get to that, we’ll run the program first.

Download a copy of Xcode, if you don’t have it already, and install it. Navigation to your boot drive (usually Macintosh HD), and the folder called Developer. Inside, there will be a folder called Applications. Xcode, and some other programs you will be using, is in there.

Xcode is located at /Developer/Applications

Location of Xcode.app

Drag it to your dock, or create an alias for it in your Applications folder. Launch Xcode. The first thing you’ll see is the launch window:

Xcode Launch Window (With Highlighting)

Xcode Launch Window (New Project Highligted)

Click on “Create a new Xcode project,” or select File > New Project (⇧⌘N). The button is highlighted in the image above. You will be greeted by the following window:

Xcode's New Image Window

Xcode's New Image Window

Select Application under Mac OS X on the left, and choose Command Line Tool on the right. Make sure the Type drop-down menu in the middle is set to Foundation. Click Choose…

Name your project, and save it somewhere on your hard drive. In a few moments, you’ll see Xcode’s main interface:

Xcode

Xcode's Main Window

We’ll take more about the parts of the window in later sections. Click on the file called Hello World.m, or something similar. This should bring up the editor window. Replace the code in the editor view with the code above, so that it looks like this:

Hello, World entered in Xcode

The Code in Xcode's Editor

Don’t worry about all the colors—we’ll discuss that later. When you have entered the code, save the file, and click the “Build and Run” or “Build and Go” button in the toolbar.

If you’ve made a mistake when typing it in, the toolbar at the bottom of Xcode’s window will change, and a message bubble will appear:

Xcode tells you when you've made a mistake

Xcode Tells You About Errors

Go back, and check the code.

When everything is working, you’ll see yet another window:

Xcode Displays the Result of the Code in the Console

Xcode Displays the Result of the Program

The output is as follows:

2010-09-03 10:47:32.414 Hello World[25379:a0f] Hello, World!

The beginning of the line shows the date and time, followed by the name of the program, and bunch of gibberish. But at the end of the line is the text that you expected to see: The program has written the words “Hello, World!” onto the screen.

Throughout the rest of these tutorials, the text that appears before that actual text that is outputted will be omitted for brevity.

Code, Demystified

Now that you’ve created a working program, let’s talk about how it works.

In Objective-C, a capital and lowercase letter mean different things. So, main, Main, and mAin are three completely different things, and cannot be used interchangeably. Also note that white space—spaces, tabs, and blank lines are ignored. You can use this to format your code properly. Take advantage of this freedom to properly format your code.

The first line of the program is a comment:

// First program example

Comments exist solely for the benefit of the programmer. Comments are important, because they allow the developer to explain a thought process. They help demystify the code, and make documenting the code sometime down the road easier. Comments help during the debugging process, or when you revisit your code some time later. It also helps other people who may use your code understand why things are the way the are. The compiler ignores comments, so you can type anything into a comment.

There are two types of comments in Objective-C. One is shown above, in which every line of the comment is preceded by two slashes. This type of comment ends at the end of the line.

A comment can also be written across multiple lines, with the following syntax:

/*
A multi-line comment can be inserted
by using a slash
and then an asterisk.
The comment can be as long as you want,
but make sure you close it
with an asterisk, then a slash. */

Which style you choose is a matter of preference, or as the situation dictates.

The next line of the program imports, or brings into your project, a file called Foundation.h:

#import <Foundation/Foundation.h>

The file in question is a system file, and that is why the name is enclosed in the brackets < and >. If you were importing a local file , you would enclose the file name in double quotes “ and ”.  This file is imported because code later in the file requires information that is contained in this file;  you are telling the compiler to look up the information in that file as necessary.

The following line declares a function called main:

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

main is a function that is where every C or C-based program begins. It is a reserved name, which means that you can’t have a function named main. The word int that precedes main is a declaration of the return type of the function. These topics will be discussed in further chapters.

After identifying main to the compiler, you tell the system what to do when it is called. These statements are enclosed in the braces { and } that surround the next few lines. Every opening brace has to be matched with a closing brace.

The first statement in main is as follows:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

This involves memory management, which is a topic thoroughly discussed in upcoming chapters.

The next line calls NSLog, which, along with the NSAutoreleasePool from above, is a function brought in by Foundation.h, which you imported.

NSLog (@"Hello, World!");

This line tells the function NSLog, which is designed to output text, to print the characters Hello, World! on the screen.

The leading @ in front of the string signifies to the compiler that this is an NSString (another object brought in from the Foundation.h file), not a C-style string. For the most part, you will be using NSStrings, rather than C-style strings.

All statements, or lines that indicate some action, must be terminated with a semicolon ; just like regular sentences are terminated with a period.

The next line is part of the NSAutoreleasePool, and its purpose and meaning will be discussed in a later chapter.
The final line tells the main method to return the value 0. Remember that the int the preceded main tells the system that this function will return a value. This value is 0. By convention, a return value of zero indicates that the function was successful.

return 0;

This line is followed by a closing brace, signifying the end of the main function.

If you look back at the window that displays the output of your program, you should see the line

Program exited with status value:0.

This is an indication of the return value of main.

Congratulations, you have created your first program in Objective-C!

Learn Objective-C in 24 Days


Yep, that title says 24 DAYS, not hours. You can’t learn a programming language in 24 hours. Publishers say you can, but that’s just for marketing purposes. To really get to learn a language, to the point where you don’t have to look back through the book every other line, takes time. It takes time to do the exercises. It takes time to formulate questions, and answer them for yourself (although I’ll be glad to answer any to the best of my ability).It takes time to let the language sink in.

I’m starting a series that will attempt to teach the Objective-C language. As Kochan did in his book (see my Resources page), I will attempt to teach plain C and Obj-C as one language. I don’t know how long it’ll take to complete—we’ll see. I want to do a solid job of teaching the language though. This post will be updated as an index of all the lessons. I hope to have the first one out by the end of the week.

My goal is to teach the series at a comfortable pace for most people. I want it to be a fun and engaging experience, and an easy place for beginners to begin their coding journey. As always, comments and criticisms are appreciated.

Download a copy of Xcode, and get ready to learn!

Directory of Lessons:

  1. Goals for this Course
  2. A Brief History of Objective-C
  3. Language Concepts
  4. How Programming Languages Work: A Brief Overview
  5. Lesson 1: Hello, World!
  6. Extending “Hello World”
  7. Reserved Keywords
  8. Lesson 2: Basic Variables
  9. Escape Sequences
  10. Format Specifiers
  11. Lesson 3: Object-Oriented Programming
  12. Integer Operations
  13. Floating-Point Operations
  14. ASCII, Booleans, Characters
  15. Lesson 4: if() Statements & Booleans
  16. Inside the if() Statement
  17. The Switch Statement
  18. Lesson 5: Loops
  19. Incrementation
  20. Loop Aids
  21. Lesson 6: Objects: Splitting Classes
  22. Lesson 6: Objects: Properties
  23. Encapsulation
  24. Methods (in detail)
  25. Lesson 6: Objects: Extending the Fraction Class
  26. Pointers
  27. Lesson 6: Objects: Inheriting iVars and Methods
  28. Lesson 6: Objects: Inheriting, Extending, and Overriding
  29. Lesson 6: Objects: Miscellaneous Inheritance Topics
  30. Lesson 6: Objects: Introspection
  31. Lesson 6: Objects: Dynamic Typing
  32. The Preprocessor
  33. Conditional Compilation
  34. Variable Scope
  35. Lesson 7: Enumerated types and typedefs
  36. Lesson 8: Categories
  37. Lesson 9: Protocols
  38. Lesson 10: Memory Management
  39. Lesson 11: Object Initialization
  40. Complex Initializers
  41. Lesson 12: Exception Handling
  42. Lesson 13: Key-Value Coding
  43. Advanced KVC
  44. Lesson 14: Structs and Unions
  45. Structs and Objects
  46. Foreach Loop
  • Welcome

    My goal is to make CupsOfCocoa into a beautiful source for beginners to the iPhone platform to get started. Subscribe below for more, and stay tuned!

  • Contact Me

    If you need to contact me for any reason, feel free to send me an email.
  • The Giving Spirit

    If you've found this site helpful, would you consider donating a little sum? Any amount is appreciated...Thanks so much!

  • Roadmap

  • Enter your email address to follow this blog and receive notifications of new posts by email.

    Join 220 other followers

  • Back to the Past

    May 2020
    S M T W T F S
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  
  • Time Machine

  • You count!

    • 622,649 views
  • Worldwide Stats

    free counters
%d bloggers like this: