MOBILE

The Language of Apple Platforms : Objective-C Programming Basics

9/14/2010 5:03:59 PM
We’ve explored the notion of classes, methods, and instance variables, but you probably still don’t have a real idea of how to go about making a program do something. ‘So, this section reviews several key programming tasks that you’ll be using to implement your methods:

Declaring Variables

Earlier we documented what instance variables in your interface file will look like, but we didn’t really get into the process of how you declare (or “define”) them (or use them). Instance variables are also only a small subset of the variables you’ll use in your projects. Instance variables store information that is available across all the methods in your class—but they’re not really appropriate for small temporary storage tasks, such as formatting a line of text to output to a user. Most commonly, you’ll be declaring several variables at the start of your methods, using them for various calculations, and then getting rid of them when ‘you’ve finished with them.

Whatever the purpose, you’ll declare your variables using this syntax:

<Type> <Variable Name>;
The type is either a primitive data type or the name of a class that you want to instantiate and use.
Primitive Data Types

Primitive data types are defined in the C language and are used to hold very basic values. Common types you’ll encounter include the following:

int Integers (whole numbers such as 1, 0, and -99)

float Floating-point numbers (numbers with decimal points in them)

double Highly precise floating-point numbers that can handle a large number of digits

For example, to declare an integer variable that will hold a user’s age, you might enter the following:

int userAge;
After a primitive data type is declared, the variable can be used for assignments and mathematical operations. The following code, for example, declares two variables, userAge and userAgeInDays, and then assigns a value to one and calculates the other:
int userAge;
int userAgeInDays;
userAge=30;
userAgeInDays=userAge*365;
Pretty easy, don’t you think? Primitive data types, however, will make up only a very small number of the variables types that you use. Most variables you declare will be used to store objects.
Object Data Types and Pointers

Just about everything that you’ll be working with in your iPhone applications will be an object. Text strings, for example, will be instances of the class NSString. Buttons that you display on the screen are objects of the class UIButton. You’ll learn about several of the common data types in the next hour’s lesson. Apple has literally provided hundreds of different classes that you can use to store and manipulate data.

Unfortunately for us, for a computer to work with an object, it can’t just store it like a primitive data type. Objects have associated instance variables and methods, making them far more complex. To declare a variable as an object of a specific class, we must declare the variable as a pointer to an object. A pointer references the place in memory where the object is stored, rather than a value. To declare a variable as a pointer, prefix the name of the variable with an asterisk. For example, to declare a variable of type NSString with the intention of holding a user’s name, we might type this:

NSString *userName;
Once declared, you can use the variable without the asterisk. It is only used in the declaration to identify the variable as a pointer to the object.

By the Way

When a variable is a pointer to an object, it is said to reference or point to the object. This is in contrast to a variable of a primitive data type, which is said to store the data.

Even after a variable has been declared as a pointer to an object, it still isn’t ready to be used. Xcode, at this point, only knows what object you intend the variable to reference. Before the object actually exists, you must manually prepare the memory it will use and perform any initial setup required. This is handled via the processes of allocation and initialization—which we review next.

Allocating, Initializing, and Releasing Objects

Before an object can be used, memory must be allocated and the contents of the object initialized. This is handled by sending an alloc message to the class that you’re going to be using, followed by an init message to what is returned by alloc. The syntax you’ll use is this:

[[<class name> alloc] init];
For example, to declare and create a new instance of UILabel class, you could use the following code:
UILabel *myLabel;
myLabel=[[UILabel alloc] init];
Once allocated and initialized, the object is ready to use.

By the Way

We haven’t covered the method messaging syntax in Objective-C, but we’ll do so shortly. For now, it’s just important to know the pattern for creating objects.

Convenience Methods

When we initialized the UILabel instance, we did create a usable object, but it doesn’t yet have any of the additional information that makes it useful. Properties such as what the label should say or where it should be shown on the screen have yet to be set. We would need to use several of the object’s other methods to really make use of the object.

These configuration steps are sometimes a necessary evil, but Apple’s classes often provide a special initialization method called a convenience method. These methods can be invoked to setup an object with a basic set of properties so that it can be used almost immediately.

For example, the NSURL class, which you’ll be using later on to work with web addresses, defines a convenience method called initWithString.

To declare and initialize an NSURL object that points to the website http://www.teachyourselfiphone.com, we might type the following:

NSURL *iPhoneURL;
iPhoneURL=[[NSURL alloc] initWithString:@"http://www.teachyourselfiphone.com/"];

Without any additional work, we’ve allocated and initialized a URL with an actual web address in a single line of code.

Did You Know?

In this example, we actually created another object, too: an NSString. By typing the @ symbol followed by characters in quotes, you allocate and initialize a string. This feature exists because strings are so commonly used that having to allocate and initialize them each time you need one would make development quite cumbersome.

Using Methods and Messaging

You’ve already seen the methods used to allocate and initialize objects, but this is only a tiny picture of the methods you’ll be using in your apps. Let’s start by reviewing the syntax of methods and messaging.

Messaging Syntax

To send an object a message, give the name of the variable that is referencing the object followed by the name of the method—all within square brackets. If you’re using a class method, just provide the name of the class rather than a variable name:

[<object variable or class name> <method name>];
Things start to look a little more complicated when the method has parameters. A single parameter method call looks like this:
[<object variable> <method name>:<parameter value>];
Multiple parameters look even more bizarre:
[<object variable> <method name>:<parameter value> additionalParameter:<parameter value>];

An actual example of using a multiple parameter method looks like this:
[userName compare:@"John" options:NSCaseInsensitive];
Here an object userName (presumably an NSString) uses the compare:options method to compare itself to the string "John" in a non-case-sensitive manner. The result of this particular method is a Boolean value (true or false), which could be used as part of an expression to make a decision in your application. (We’ review expressions and decision making next!)

Did You Know?

Throughout the lessons, methods are referred to by name. If the name includes a colon (:), this indicates a required parameter. This is a convention that Apple has used in their documentation and that ’has been adopted for this book.


Did You Know?

A useful predefined value in Objective-C is nil. The nil value indicates a lack of any value at all. You’ll use nil in some methods that call for a parameter that you don’t have available. A method that receives nil in place of an object can actually pass messages to nil without creating an error—nil simply returns another nil as the result.

‘This is used a few times later in the book, and should give you a better clearer picture of why this behavior is something we’d actually want to happen!

Nested Messaging

Something that you’ll see when looking at Objective-C code is that the result of a method is sometimes used directly as a parameter within another method. In some cases, if the result of a method is an object, a developer will send a message directly to that result.

In both of these cases, using the results directly avoids the need to create a variable to hold the results. Want an example that puts all of this together? We’ve got one for you!

Assume you have two NSString variables, userFirstName and userLastName, that you want to capitalize and concatenate, storing the results in another NSStringfinalString. The NSString instance method capitalizedString returns a capitalized string, while stringByAppendingString takes a second string as a parameter and concatenates it onto the string invoking the message. Putting this together (disregarding the variable declarations), the code looks like this: called

tempCapitalizedFirstName=[userFirstName capitalizedString];
tempCapitalizedSecondName=[userLastName capitalizedString];
finalString=[tempCapitalizedFirstName
stringByAppendingString:tempCapitalizedSecondName];

Instead of using these temporary variables, however, you could just substitute the method calls into a single combined line:

finalString=[[userFirstName capitalizedString] stringByAppendingString:[userLastName
capitalizedString]];

This can be a powerful way to structure your code, but can also lead to long and rather confusing statements. Do what makes you comfortable—both approaches are equally valid and have the same outcome.

By the Way

A confession. I have a difficult time referring to using a method as sending a “message to an object.” Although this is the preferred terminology for OOP, all we’re really doing is executing an object’s method by providing the name of the object and the name of the method.

Blocks

Although most of your coding will be within methods, Apple recently introduced “blocks” to the iOS frameworks. Sometimes referred to as a handler block in the iOS documentation, these are chunks of code that can be passed as a value when calling a method. They provide instructions that the method should run when reacting to a certain event.

For example, imagine a personInformation object with a method called setDisplayName that would define a format for showing a person’s name. Instead of just showing the name, however, setDisplayName might use a block to let you define, programmatically, how the name should be shown:

[personInformation setDisplayName:^(NSString firstName, NSString lastName)
{
// Implement code here to modify the first name and last name
// and display it however you want.
}];

Interesting, isn’t it? Blocks are new to iPhone development and will very rarely be used in the book. When you start developing motion-sensitive apps, for example, you will pass a block to a method to describe what to do when a motion occurs.

Where blocks are used, we’ll walk through the process. If you’d like to learn more about these strange and unusual creatures, read Apple’s “A Short Practical Guide to Blocks” in the Xcode documentation.

Expressions and Decision Making

For an application to react to user input and process information, it must be capable of making decisions. Every decision in an app boils down to a “yes” or “no” result based on evaluating a set of tests. These can be as simple as comparing two values, to something as complex as checking the results of a complicated mathematical calculation. The combination of tests used to make a decision is called an expression.

Using Expressions

If you recall your high school algebra, you’ll be right at home with expressions. An expression can combine arithmetic, comparison, and logical operations.

A simple numeric comparison checking to see whether a variable userAge is greater than 30 could be written as follows:

userAge>30
When working with objects, we need to use properties within the object and values returned from methods to create expressions. To check to see whether a string stored in an object userName is equal to ""John"”, we could use this:
[userName compare:@"John"]
Expressions aren’t limited to the evaluation of a single condition. We could easily combine the previous two expressions to find a user who is over 30 and named John:
userAge>30 && [userName compare:@"John"]

By the Way: Common Expression Syntax

() Groups expressions together, forcing evaluation of the innermost group first

== Tests to see whether two values are equal (e.g., userAge==30)

!= Tests to see whether two values are not equal (e.g., userAge!=30)

&& Implements a logical AND condition (e.g., userAge>30 && userAge<40)

|| Implements a logical OR condition (e.g., userAge>30 || userAge<10)

! Negates the result of an expression, returning the opposite of the original result (e.g., !(userAge==30) is the same as userAge!=30)

For a complete list of C expression syntax, you may want to refer to http://www.cs.drexel.edu/~rweaver/COURSES/ISTC-2/TOPICS/expr.html.


As ’mentioned repeatedly, you’re going to be spending lots of time working with complex objects and using the methods within the objects. You can’t make direct comparisons or between objects as you can with simple primitive data types. To successfully create expressions for the myriad objects you’ll be using, ’you must review each object’s methods and properties.

Making Decisions with if-then-else and switch Statements

Typically, depending on the outcome of the evaluated expression, different code statements are executed. The most common way of defining these different execution paths is with an if-then-else statement:

if (<expression>) {
// do this, the expression is true.
} else {
// the expression isn't true, do this instead!
}

For example, consider the comparison we used earlier to check a userName NSString variable to see whether its contents were set to a specific name. If we want to react to that comparison, we might write the following:

If ([userName compare:@"John"]) {
userMessage=@"I like your name";
} else {
userMessage=@"Your name isn't John, but I still like it!";
}

Another approach to implementing different code paths when there are potentially many different outcomes to an expression is to use a switch statement. A switch statement checks a variable for a value, and then executes different blocks of code depending on the value that is found:

switch (<numeric value>) {
case <numeric option 1>:
// The value matches this option
break;
case <numeric option 2>:
// The value matches this option
break;
default:
// None of the options match the number.
}

Applying this to a situation where we might want to check a user’s age (stored in userAge) for some key milestones and then set an appropriate userMessage string if they are found, the result might look like this:

switch (userAge) {
case 18:
userMessage=@"Congratulations, you're an adult!";
break;
case 21:
userMessage=@"Congratulations, you can drink champagne!";
break;
case 50:
userMessage=@"You're half a century old!";
break;
default:
userMessage=@"Sorry, there's nothing special about your age.";
}
Repetition with Loops

Sometimes you’ll have a situation where you need to repeat several instructions over and over in your code. Instead of typing the lines repeatedly, you can loop over them. A loop defines the start and end of several lines of code. As long as the loop is running, the program executes the lines from top to bottom, and then restarts again from the top. The loops you’ll use are of two types: count based and condition based.

In a count-based loop, the statements are repeated a certain number of times. In a condition-based loop, an expression determines whether a loop should occur.

The count-based loop you’ll be using is called a for loop, with this syntax:

for (<initialization>;<test condition>;<count update>) {
// Do this, over and over!
}

The three “unknowns” in the for statement syntax are a statement to initialize a counter to track the number of times the loop has executed, a condition to check to see whether the loop should continue, and finally, an increment for the counter. An example of a loop that uses the integer variable count to loop 50 times could be written as follows:

int count;
for (count=0;count<50;count=count+1) {
// Do this, 50 times!
}
The for loop starts by setting the count variable to 0. The loop then starts and continues as long as the condition of count<50 remains true. When the loop hits the bottom curly brace (}) and starts over, the increment operation is carried out and count is increased by 1.

Did You Know?

In C and C-like languages, like Objective-C, integers are usually incremented by using ++ at the end of the variable name. In other words, rather than using count=count+1, most frequently you’ll encounter count++, which does the same thing. Decrementing works the same way, but with --.

In a condition-based loop, the loop continues either while an expression remains true. There are two variables of this loop type that you’ll encounter, while and do-while:
while (<expression>) {
// Do this, over and over, while the expression is true!
}

and

do {
// Do this, over and over, while the expression is true!
} while (<expression>);

The only difference between these two loops is when the expression is evaluated. In a standard while loop, the check is done at the beginning of the loop. In the do-while loop, however, the expression is evaluated at the end of every loop.

For example, suppose you are asking users to input their name and you want to keep prompting them until they type John. You might format a do-while loop like this:

do {
// Get the user's input in this part of the loop
} while (![userName compare:@"John"]);

The assumption is that the name is stored in a string object called userName. Because you wouldn’t have requested the user’s input when the loop first starts, you would use a do-while loop to put the test condition at the end. Also, the value returned by the string compare method has to been negated with the ! operator, because you want to continue looping as long as the comparison of the userName to “John" isn’t true.

Loops are a very useful part of programming, and, along with the decision statements, will form the basis for structuring the code within your object methods. They allow code to branch and extend beyond a linear flow.

Although ’an all-encompassing picture of programming is beyond the scope of this book, this should give you some sense of what to expect in the rest of this book. ’Let’s now close out the hour with a topic that causes quite a bit of confusion for beginning developers: memory management.

Other  
  •  The Language of Apple Platforms : Exploring the Objective-C File Structure
  •  The Language of Apple Platforms : Object-Oriented Programming and Objective-C
  •  Using the iPhone Simulator
  •  Introduction to Xcode Simulator
  •  Creating a Development Provisioning Profile on iPhone
  •  Preparing Your System and iPhone for Development
  •  Understanding Mobile Networking and Remote Access in Vista
  •  Creating Connections for Remote Access in Vista
  •  Configuring Mobile Connection Properties in Vista
  •  Establishing Mobile Connections in Vista
  •  Wireless Networking in Vista
  •  Configuring Power Management Settings in Vista
  •  Configuring Networking for Laptops
  •  Mobile Commerce Applications, Part 2
  •  Mobile Commerce Applications, Part 1
  •  J2ME: User Interface
  •  Java Me Programming Steps
  •  The Hello-World Midlet
  •  
    Most View
    Best Free Web Storage (Part 2)
    Canon EOS C500 and EOS-1DC: 4K Cameras Now!
    Windows 7 : Protecting Your Data from Loss and Theft - Disk Organization for Data Safety, BitLocker Disk Encryption
    The Personalised Internet (Part 2)
    The 50 Best Headphones You Can Buy (Part 2)
    Anthem MRX 700 – The Greatness Home Cinema Amplifier
    Latest Gadgets, Gizmos And Geek Toys – December 2012
    Active Directory 2008 : Configuring Replication (part 1) - Connection Objects,The Knowledge Consistency Checker, Intrasite Replication
    Buying Guide: All-In-One Multifunction Printers – May 2013 (Part 1)
    Push Your Phone To Its Limits (Part 2) : Swype for tablets
    Top 10
    Windows Phone 7 : Applying Textures (part 2) - Preparing the Effect for Texture Mapping
    Windows Phone 7 : Applying Textures (part 1) - Applying the Texture to an Object
    Windows 7 : Programming WMI Support (part 5) - Techniques for Testing WMI Driver Support, WMI Event Tracing
    Windows 7 : Programming WMI Support (part 4) - Troubleshooting Specific WMI Problems
    Windows 7 : Programming WMI Support (part 3) - Firing WMI Events
    Windows 7 : Programming WMI Support (part 2) - WMI Requirements for WDM Drivers ,WMI Class Names and Base Classes
    Windows 7 : Programming WMI Support (part 1) - WMI Architecture, Registering as a WMI Data Provider, Handling WMI Requests
    Western Digital My Passport Slim 1TB - Slim and Portable
    Five Microsoft Services To Make Any Business Smarter
    Internet Explorer 11 - Speedy On Windows 7, Tailored For Windows 8.1