Object Oriented Programming: Objective-C
Object Oriented Programming: Objective-C
Objective-C
Presentation by ThongTD
Overview
Objective-C is an object oriented language.
follows ANSI C style coding with methods
from Smalltalk
There is no formal written standard
Relies mostly on libraries written by others
Flexible almost everything is done at runtime.
Dynamic Binding
Dynamic Typing
Dynamic Linking
The Cocoa API
Primarily the most frequently used
frameworks nowadays.
Developed by Apple from NeXTSTEP and
OPENSTEP
Has a set of predefined classes and types
such as NSnumber, NSstring, Nsdate, etc.
NS stands for NeXT-sun
Includes a root class NSObject where words
like alloc, retain, and release come from
Creating Objects
Accessors
Calling Methods
Logging
Designing a Class Interface
Class Implementation
Properties
Basic Memory Management
Calling Methods on Nil
Categories
Creating Objects
There are two main ways to create an object. The
first is the one you saw before:
The code on the second line is not reading the instance variable
directly. It's actually calling a method named caption. In most
cases, you don't add the "get" prefix to getters in Objective-C.
Whenever you see code inside square brackets, you are
sending a message to an object or a class.
Accessors (Continue)
Dot Syntax
The dot syntax for getters and setters is new in
Objective-C 2.0, which is part of Mac OS X 10.5:
photo.caption = @"Day at the Beach";
output = photo.caption;
You can use either style, but choose only one for
each project. The dot syntax should only be used
setters and getters, not for general purpose methods.
Calling Methods
To get started as quickly as possible,
let's look at some simple examples. The
basic syntax for calling a method on an
object is this:
[object method];
[object methodWithInput:input];
Calling Methods (Continue)
Methods can return a value:
output = [object methodWithOutput];
output = [object methodWithInputAndOutput:input];
@implementation Photo
+(id)getClassName {
return [self getClassName];
}
-(NSString*) caption {
return caption;
}
- (NSString*) photographer {
return photographer;
}
@end
Class Implementation (Continue)
This part of the code starts with @implementation and the class
name, and has @end, just like the interface. All methods must
appear between these two statements. The getters should look
very familiar if you've ever written code, so let's move on to the
setters, which need a bit more explanation:
- (void) setCaption: (NSString*)input {
[caption autorelease];
caption = [input retain];
}
- (void) setPhotographer: (NSString*)input {
[photographer autorelease];
photographer = [input retain];
}
Class Implementation (Continue)
Each setter deals with two variables.
The first is a reference to the existing
object, and the second is the new input
object. In a garbage collected
environment, we could just set the new
value directly:
- (void) setCaption: (NSString*)input
{ caption = input; }
Class Implementation (Continue)
But if you can't use garbage collection, you need to release the
old object, and retain the new one. There are actually two ways
to free a reference to an object: release and autorelease. The
standard release will remove the reference immediately. The
autorelease method will release it sometime soon, but it will
definitely stay around until the end of the current function
(unless you add custom code to specifically change this). The
autorelease method is safer inside a setter because the
variables for the new and old values could point to the same
object. You wouldn't want to immediately release an object
which you're about to retain. This may seem confusing right
now, but it will make more sense as you progress. You don't
need to understand it all yet.
Init
We can create an init method to set inital values for our instance
variables:
- (id) init {
if ( self = [super init] ) {
[self setCaption:@"Default Caption"];
[self setPhotographer:@"Default Photographer"];
}
return self;
}
This is fairly self-explanatory, though the second line may look a bit
unusual. This is a single equals sign, which assigns the result of [super
init] to self. This essentially just asks the superclass to do its own
initialization. The if statement is verifying that the initialization was
successful before trying to set default values.
Dealloc
The dealloc method is called on an object when it is being removed
from memory. This is usually the best time to release references to all
of your child instance variables:
- (void) dealloc {
[caption release];
[photographer release];
[super dealloc];
}
On the first two lines, we just send release to each of the instance
variables. We don't need to use autorelease here, and the standard
release is a bit faster. The last line is very important. We have to send
the message[super dealloc] to ask the superclass to do its cleanup. If
we don't do this, the object will not be removed, which is a memory
leak. The dealloc method is not called on objects if garbage collection is
enabled. Instead, you implement the finalize method
Prototyping functions
When declaring or implementing
functions for a class, they must begin
with a + or -
+ indicates a “class method” that can
only be used by the class itself. In other
words, they’re for private functions.
- indicates “instance methods” to be
used by the client program (public
functions).
Properties
When we wrote the accessor methods for caption and author earlier,
you might have noticed that the code is straightforward, and could
probably be generalized. Properties are a feature in Objective-C that
allow us to automatically generate accessors, and also have some
other side benefits. Let's convert the Photo class to use properties:
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
@property (retain) NSString* caption;
@property (retain) NSString* photographer;
@end
Properties (Continue)
The @property is an Objective-C directive which declares the property.
The "retain" in the parenthesis specifies that the setter should retain the
input value, and the rest of the line simply specifies the type and the
name of the property. Now let's take a look at the implementation of the
class:
#import "Photo.h"
@implementation Photo
@synthesize caption;
@synthesize photographer;
- (void) dealloc {
[caption release];
[photographer release];
[super dealloc];
}
@end
Properties (Continue)
The @synthesize directive automatically
generates the setters and getters for us, so all
we have to implement for this class is the dealloc
method. Accessors will only be generated if they
don't already exist, so feel free to specify
@synthesize for a property, then implement your
custom getter or setter if you want. The compiler
will fill in whichever method is missing.
Basic Memory Management
If you create an object using the manual alloc style,
you need to release the object later. You should not
manually release an autoreleased object because
your application will crash if you do. Here are two
examples:
Notice how the rules for managing local references are exactly the
same, regardless of whether you're setting them as instance variables
or not. You don't need to think about how the setters are implemented.
If you understand this, you understand 90% of what you will ever need
to know about Objective-C memory management.
Calling Methods on Nil
In Objective-C, the nil object is the functional equivalent to the NULL
pointer in many other languages. The difference is that you can call
methods on nil without crashing or throwing an exception. This
technique used by the frameworks in a number of different ways, but
the main thing it means to you right now that you usually don't need to
check for nil before calling a method on an object. If you call a method
on nil that returns an object, you will get nil as a return value. We can
also use this to improve our dealloc method slightly:
- (void) dealloc {
self.caption = nil;
self.photographer = nil;
[super dealloc];
}
Calling Methods on Nil (Continue)
This works because when we set nil as an instance
variable, the setter just retains nil (which does nothing)
and releases the old value. This approach is often better
for dealloc because there's no chance of the variable
pointing at random data where an object used to be. Note
that we're using the self.<var> syntax here, which means
we're using the setter and picking up the memory
management for free. If we just directly set the value like
this, there would be a memory leak:
// incorrect. causes a memory leak.
// use self.caption to go through settercaption = nil;
Categories
Categories are one of the most useful features of Objective-C.
Essentially, a category allows you to add methods to an existing
class without subclassing it or needing to know any of the
details of how it's implemented. This is particularly useful
because you can add methods to built-in objects. If you want to
add a method to all instances of NSString in your application,
you just add a category. There's no need to get everything to
use a custom subclass. For example, if I wanted to add a
method to NSString to determine if the contents is a URL, it
would look like this:
#import <Cocoa/Cocoa.h>
@interface NSString (Utilities)
- (BOOL) isURL;
@end
Categories (Continue)
This is very similar to a class declaration. The differences are that there
is no super class listed, and there's a name for the category in
parenthesis. The name can be whatever you want, though it should
communicate what the methods inside do. Here's the implementation.
Keep in mind this is not a good implementation of URL detection. We're
just trying to get the concept of categories across:
#import "NSString-Utilities.h"
@implementation NSString (Utilities)
- (BOOL) isURL{
if ( [self hasPrefix:@"http://"] )
return YES;
else
return NO;
}
@end
Categories (Continue)
Now you can use this method on any NSString. The following code will
print "string1 is a URL" in the console:
NSString* string1 = @"http://pixar.com/";
NSString* string2 = @"Pixar";
if ( [string1 isURL] )
NSLog (@"string1 is a URL");
if ( [string2 isURL] )
NSLog (@"string2 is a URL");
Learn Objective-C
http://cocoadevcentral.com/d/learn_o
bjectivec/