Professional Documents
Culture Documents
Legal Notices
This publication is protected under the US Copyright Act of 1976 and all
other applicable international, federal, state and local laws, and all rights are
reserved, including resale rights: you are not allowed to give or sell this
book to anyone else. If you received this publication from anyone other than
How to Make iPhone Apps or App Shop, LLC, you've received a pirated copy.
Please contact us via e-mail at support@app-shop.com and notify us of the
situation.
iPhone™, iPod™ and iTunes™ are trademarks of Apple Inc., registered in the
U.S. and other countries.
Finally, use your head. Nothing in this book is intended to replace common
sense, legal, medical, metaphysical or other professional advice, and is
meant to inform and entertain the reader. So have fun with The Objective-C
Crash Course, and get your stuff done.
Autorelease ........................................................................................................31
In order to help you get over the disorientation of jumping into working with
the iPhone this crash course will show you the Objective-C approaches to
using common programming methods like looping and if-then logic.
This document will get you up to speed with the tasks that you are used to
as a programmer. However, if you do not have much experience as a
programmer and would like an introduction to programming concepts and a
deeper knowledge of Objective-C then I recommend the book Learn
Objective-C on the Mac.
Included in the bonus materials is an XCode project that has the source code
discussed here. The project is called “ProgrammingCheatSheet”. Open the
project by choosing the file ProgrammingCheatSheet.xcodeproj from the file
menu item in XCode or by using Finder.
The screen above is what you will see when you open the
ProgrammingCheatSheet project in XCode. It is marked it up here to make
it clear where the source code is located.
{, } & ;
For example:
NSString *newString =
[NSString stringWithFormat:
@"I Added This to %@.", myString];
Even though the statement above looks like it spans over three lines, the
system considers in one line of code that ends with the “;” after “myString].
The “{“ and “}” are used to group lines of code together in this family of
languages. For example,
int x = 5;
if(x == 5){
NSLog(@"True");
NSLog(@"More Stuff");
}
else{
NSLog(@"False");
}
The brackets are used to ensure that both NSLog statements above are
executed when the x == 5 condition is met.
[alert show];
The object here is “alert” and the message is “show”. Notice how the entire
object and method is contained in square brackets and there is a space
between the object and the method. In other programming languages this
statement might look something like this:
alert.show();
Other programming languages may write the same statement like this:
When you use a method that requires more than one parameter you must
supply a descriptive prefix,”:” and the parameter itself. For example,
The descriptive prefix is a unique Objective-C feature that helps you self-
document your code.
You will encounter two kinds of variables when working with Objective-C.
Objects such as the alert demonstrated above and simple types like integers
and doubles. These things can cause some confusion because they follow
different rules even though they are used in similar ways.
The first notable difference is how we declare a type versus an object. Here
is how an integer would be declared:
int number;
The type and a variable name followed by a semi-colon. Pretty simple and
probably what you would expect. Here is how a NSNumber object would be
declared:
NSNumber *numberObject;
The next significant difference is that while the integer above is ready to
use, our object have memory allocated to it and our object must be created
with an constructor (see the sections on objects and classes for more
information on this).
number = 78;
Finally, when you are finished working with an object you need to make sure
to release it.
[numberObject release];
Objects also need special care when it comes to memory management (see
the memory management section). They are worth the extra trouble since
objects generally contain a very rich feature set and are used extensively in
the Cocoa-Touch frameworks.
Using strings
Notice that you need to put an escape character, @, in front of the quoted
text when you creating strings.
Using integers
int i = 3;
NSLog(@"i = %i", i);
Using doubles
double d = 3.4;
NSLog(@"d = %f", d);
Doing arithmetic
double dPlusi = d + i;
NSLog(@"d + i = %f", dPlusi);
Using NSInteger
NSInteger ns_i = 8;
NSLog(@"ns_i = %i", ns_i);
Using NSUInteger
Using the NSNumber Class
[myObject demonstrateAnInstanceMethod];
Send a message to an object with a parameter
Send a message to an object with two parameters
Using a value returned from an object function
NSLog([myObject aFunctionReturnsThatAString]);
Assign a value to a property using dot syntax
NSLog(myObject.name);
Release an objectʼs memory allocation
[myObject release];
Arrays are lists of objects. They can be strings, numbers or custom objects.
An array can contain different types of objects. Objective-C uses the
NSMutableArray class to work with arrays. Here are some examples.
Instantiate an array
NSMutableArray *myArray = [[NSMutableArray alloc] init];
NSLog([myArray objectAtIndex:0]);
Retrieve the last object in an array
NSLog([myArray lastObject]);
Move through each element in an array
[myArray release];
Add objects to a dictionary indexed by keys
Retrieve an object from a dictionary with a key
NSLog([dictionary objectForKey:@"B"]);
Release a dictionary
[dictionary release];
int x = 5;
if(x == 5){
NSLog(@"True");
}
else{
NSLog(@"False");
}
Switch statements are used when a program must evaluate an option based
on a list of conditions. This is sometimes referred to as a “Case” statement.
Here is how you code a switch statement:
switch (x) {
case 1:
NSLog(@"i = 1");
break;
case 5:
NSLog(@"i = 5");
break;
default:
NSLog(@"default case");
break;
}
Loops are used when a program must repeat a set of instructions many
times in a row. Objective-C has a few options that may be used when loops
are needed:
Using for loops
x = 0;
do{
NSLog(@"x = %i", x);
x++;
}
while(x <= 4);
Using while loops
x = 0;
while (x <= 4 ) {
NSLog(@"x = %i", x);
x++;
}
@interface means that this is definition of the class, myClass is the name of
our subclass, : means that this class is inheriting and NSObject is the name
of the class that we are inheriting from.
The code below shows a complete subclass that inherits from NSObject and
it also happens to be the class used in the previous section, How to Use
Objects, Properties and Methods. See that section for demonstrations on
how to use the properties and methods of this subclass.
Generally, when you create your own subclass you use two files – an
interface file (ends in h) and an implementation file (ends in m). You must
add code to both files when writing code for your subclass.
XCode will create both of these files and fill in the details when you use
XCode to add a new NSObject subclass to your project.
#import <Foundation/Foundation.h>
@end
#import "myClass.h"
@implementation myClass
@synthesize name;
-(void) dealloc{
[name release];
[super dealloc];
}
@end
Class methods may be used even if an object has not been created. You
know a method is a class method when it as a “+” in front of the (void)
instead of a “-“. Here is how you would add a class method to your
subclass:
#import <Foundation/Foundation.h>
+(void) demonstrateAClassMethod;
@end
#import "myClass.h"
@implementation myClass
@synthesize name;
-(void) dealloc{
[name release];
[super dealloc];
}
+(void) demonstrateAClassMethod{
NSLog(@"Class Method");
}
@end
To use a class method, you must send a message to the class and not the
object.
Instance methods require an object to have been instantiated. You can tell
that a method is an instance method when it has a “-“ before (void). Here is
how you would code an instance method:
#import <Foundation/Foundation.h>
-(void) demonstrateAnInstanceMethod;
+(void) demonstrateAClassMethod;
@end
#import "myClass.h"
@implementation myClass
@synthesize name;
-(void) dealloc{
[name release];
[super dealloc];
}
-(void) demonstrateAnInstanceMethod{
NSLog(@"Instance Method");
}
+(void) demonstrateAClassMethod{
NSLog(@"Class Method");
}
@end
#import <Foundation/Foundation.h>
-(void) demonstrateAnInstanceMethod;
+(void) demonstrateAClassMethod;
-(void) demonstrateAnObjectMethodWithThisParameter:(NSString *) aParameter;
@end
#import "myClass.h"
@implementation myClass
@synthesize name;
-(void) dealloc{
[name release];
[super dealloc];
}
-(void) demonstrateAnInstanceMethod{
NSLog(@"Instance Method");
}
+(void) demonstrateAClassMethod{
NSLog(@"Class Method");
}
@end
See the complete code below for examples of methods that use more than
one parameter, a method that references the object it is contained in and a
function. This code is contained in aMethodWithTwoParameters,
aMethodThatReferencesSelf and aFunctionReturnsThatAString respectively.
#import <Foundation/Foundation.h>
-(id)initWithNewName;
-(void) demonstrateAnInstanceMethod;
+(void) demonstrateAClassMethod;
-(void) demonstrateAnObjectMethodWithThisParameter:(NSString *) aParameter;
-(void) aMethodWithTwoParameters:(NSString *) firstParameter
aInteger:(int) secondParameter;
-(void) aMethodThatReferencesSelf;
-(NSString *) aFunctionReturnsThatAString;
@end
#import "myClass.h"
@implementation myClass
@synthesize name;
-(id)initWithNewName{
if (self = [super init]){
self.name = @"New Name";
}
return self;
}
-(void) dealloc{
[name release];
[super dealloc];
}
-(void) demonstrateAnInstanceMethod{
NSLog(@"Instance Method");
}
+(void) demonstrateAClassMethod{
NSLog(@"Class Method");
}
-(void) demonstrateAnObjectMethodWithThisParameter:(NSString *) aParameter{
NSLog(aParameter);
}
-(void) aMethodWithTwoParameters:(NSString *) firstParameter
aInteger:(int) secondParameter{
NSLog(@"First Parameter:%@, Second Parameter: %i:",
firstParameter, secondParameter);
}
-(void) aMethodThatReferencesSelf{
NSLog(@"Self:");
[self demonstrateAnInstanceMethod];
}
-(NSString *) aFunctionReturnsThatAString{
return @"A Returned String";
}
@end
When you are programming on the iPhone you need to worry about memory
- the iPhone does not use a garbage collection system to automate assigning
and releasing blocks of memory.
Reference Counting
The system used in the iPhone to deal with memory is called reference
counting. A number is assigned to every object that is created that is equal
to the number of times that object has been referenced by another object.
When you create an object you generally use this pattern. First, you declare
an object of a class.
myClass *myObject;
Then you use the alloc method to allocate memory and the init constructor
to return an instance of the class.
When the alloc method is used the reference count of the myObject class is
incremented from 0 to 1.
As myObject goes through it’s life cycle other objects that require it to stick
around will send the myObject a retain message. This again increments the
retain count so that the object can be sure that myObject will not go out of
memory while it is still needed. Here is how the retain message is sent.
[myObject retain];
[myObject release];
This retain and release pattern corresponds to adding and subtracting from
the retain count. When the object reaches 0 then it disappears and its
memory is reclaimed by the system.
Normally, we use this alloc, use and release pattern when working with
objects. If we do need to send a retain message we must match it with a
corresponding release message. That way, we know that we always have
the object when we needed but that it will free up memory when we do not
need it.
However, there are times when this system will not work. For example,
many classes have functions that return objects. The function cannot
release the object before it returns the object; whatever is using the function
will not be able to work with the object if it is released.
When you return an object from function you simply send the autorelease
message to the object before return it to the system.
-(myObject *) getAnObject{
myClass *myObject;
myObject = [[myClass alloc] init];
[myObject autorelease];
return myObject;
}
When you use autorelease in this way it is best to assume that the object
being returned will only be used temporarily. If the other components in
your system need the returned object for a longer period of time send a
retain message to keep the object around.
• When you use alloc and init to create an object you will need to send a
release message when you are finished
• When you use properties in your class definitions with the retain keyword
the system is creating code for your (in the background) that automatically
retains the object. This is why you need to release these objects in the
dealloc method.
• The dealloc method is executed when the retain count of an object reaches
zero.
• One huge problem that occurs when objects attempt to access another
object that has been released from memory is that this causes the app to
crash.
• Learn how to use Instruments and NSZombie to diagnose and fix these
memory problems.
• These memory techniques only apply to objects and not C types. When
you are working with things like int, BOOL or double you do not need to
worry about the retain and release pattern.
At this point, you should be getting familiar enough with the Objective-C
language to fully implement your iPhone app with the help of the main How
to Make an iPhone App book. If you want to learn about the Objective-C
language in greater detail I would recommend this book: Learn Objective-C
on the Mac. If this is your first exposure to any programming that I suggest
that you read Learn C on the Mac. as well in order to learn the basics of
programming in the C language.