0% found this document useful (0 votes)
54 views

Object Oriented Programming: Objective-C

Objective-C is an object-oriented language that follows ANSI C style coding conventions and includes methods from Smalltalk. It uses dynamic binding, typing, and linking. The Cocoa API is primarily used for iOS and macOS development and includes classes like NSString and NSDate. Key concepts include creating and accessing objects, calling methods, logging, designing class interfaces, implementing classes, and using properties and memory management.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
54 views

Object Oriented Programming: Objective-C

Objective-C is an object-oriented language that follows ANSI C style coding conventions and includes methods from Smalltalk. It uses dynamic binding, typing, and linking. The Cocoa API is primarily used for iOS and macOS development and includes classes like NSString and NSDate. Key concepts include creating and accessing objects, calling methods, logging, designing class interfaces, implementing classes, and using properties and memory management.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 44

Object Oriented Programming

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: 

 NSString* myString = [NSString string];

This is the more convenient automatic style. In


this case, you are creating an autoreleased
object, which we'll look at in more detail later. In
many cases, though, you need to create an
object using the manual style:
Creating Objects (Continue)
 NSString* myString = [[NSString alloc] init];

This is a nested method call. The first is the alloc method


called on NSString itself. This is a relatively low-level call
which reserves memory and instantiates an object. The
second piece is a call to init on the new object. The init
implementation usually does basic setup, such as creating
instance variables. The details of that are unknown to you
as a client of the class. In some cases, you may use a
different version of init which takes input:

 NSNumber* value = [[NSNumber alloc] initWithFloat:1.0];


Accessors
All instance variables are private in Objective-C by default, so
you should use accessors to get and set values in most cases.
There are two syntaxes:

 This is the traditional 1.x syntax: 


[photo setCaption:@"Day at the Beach”];
output = [photo caption];

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];

You can call methods on classes too, which is how


you create objects. In the example below, we call the
string method on the NSString class, which returns a
new NSString object:
id myObject = [NSString string];
Calling Methods (Continue)
The id type means that the myObject variable can
refer to any kind of object, so the actual class
and the methods it implements aren't known
when you compile the app. In this example, it's
obvious the object type will be an NSString, so
we can change the type: 
NSString* myString = [NSString string];
Calling Methods (Continue)
 This is now an NSString variable, so the compiler
will warn us if we try to use a method on this
object which NSString doesn't support. Notice
that there's a asterisk to the right of the object
type. All Objective-C object variables are pointers
types. The id type is predefined as a pointer type,
so there's no need to add the asterisk.
Nested Messages
In many languages, nested method or function
calls look like this:
function1 ( function2() );
The result of function2 is passed as input to
function1. In Objective-C, nested messages look
like this: 
[NSString stringWithFormat:[prefs format]];
Avoid nested nesting more than two message
calls on a single line, as it easily gets
unreadable.
Multi-Input Methods
 Some methods take multiple input
values. In Objective-C, a method name
can be split up into several segments. In
the header, a multi-input method looks
like this: 
-(BOOL)writeToFile:(NSString *)path
atomically:(BOOL)useAuxiliaryFile;
Multi-Input Methods (Continue)

You call the method like this: 


BOOL result = [myData
writeToFile:@"/tmp/log.txt"
atomically:NO];
These are not just named arguments.
The method name is actually
writeToFile:atomically: in the runtime
system.
Logging
 Logging messages to the console in Objective-C is
very simple. In fact, the NSLog() function is nearly
identical to the C printf() function, except there's an
additional %@ token for objects.
NSLog ( @"The current date and time is: %@",
[NSDate date] );
 You can log an object to the console. The NSLog
function calls the description method on the object,
and prints the NSString which is returned. You can
override the description method in your class to
return a custom string.
Designing a Class Interface
 The Objective-C syntax for creating a class is
very simple. It typically comes in two parts. The
class interface is usually stored in the
ClassName.h file, and defines instance variables
and public methods. The implementation is in the
ClassName.m file and contains the actual code
for these methods. It also often defines private
methods that aren't available to clients of the
class. Here's what an interface file looks like. The
class is called Photo, so the file is named
Photo.h:
Designing a Class Interface
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject
{ NSString* caption;
NSString* photographer;
}
@end
Designing a Class Interface
 First, we import Cocoa.h, to pull in all of the basic
classes for a Cocoa app. The #import directive
automatically guards against including a single
file multiple times. The @interface says that this
is a declaration of the class Photo. The colon
specifies the superclass, which is NSObject.
Inside the curly brackets, there are two instance
variables: caption and photographer. Both are
NSStrings, but they could be any object type,
including id. Finally, the @end symbol ends the
class declaration. 
Add Methods
Let's add some getters for the instance
variables: 
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- caption;
- photographer;
- @end
Add Methods (Continue)
 Remember, Objective-C methods typically leave
out the "get" prefix. A single dash before a
method name means it's a instance method. A
plus before a method name means it's a class
method. By default, the compiler assumes a
method returns an id object, and that all input
values are id. The above code is technically
correct, but it's unusual. Let's add specific types
for the return values:
Add Methods (Continue)
Let's add some getters for the instance variables: 
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
+ (id)getName;
- (NSString *)caption;
- (NSString *)photographer;
- @end
Add Methods (Continue)
 Now let's add setters: 
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
+ (id)getClassName;
- (NSString*) caption;
- (NSString*) photographer;
- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;
- @end
Class Implementation
#import "Photo.h”

@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: 

// string1 will be released automatically


NSString* string1 = [NSString string];
// must release this when done
NSString* string2 = [[NSString alloc] init];
[string2 release];
More on Memory Management
 Objective-C's memory management system is called reference
counting. All you have to do is keep track of your references,
and the runtime does the actual freeing of memory. In simplest
terms, you alloc an object, maybe retain it at some point, then
send one release for each alloc/retain you sent. So if you used
alloc once and then retain once, you need to release twice.

 That's the theory of reference counting. But in practice, there


are usually only two reasons to create an object: 1. To keep it
as an instance variable2. To use temporarily for single use
inside a function In most cases, the setter for an instance
variable should just autorelease the old object, and retain the
new one. You then just make sure to release it in dealloc as
well.
More on Memory Management
 So the only real work is managing local references inside a
function. And there's only one rule: if you create an object with
alloc or copy, send it a release or autorelease message at the
end of the function. If you create an object any other way, do
nothing. Here's the first case, managing an instance variable: 
- (void) setTotalAmount: (NSNumber*)input {
[totalAmount autorelease];
totalAmount = [input retain];
}
- (void) dealloc {
[totalAmount release];
[super dealloc];
}
More on Memory Management
 Here's the other case, local references. We only need
to release the object created with alloc: 

NSNumber* value1 = [[NSNumber alloc]


initWithFloat:8.75];

NSNumber* value2 = [NSNumber


numberWithFloat:14.78];

// only release value1, not value2


[value1 release];
More on Memory Management
 And here's a combo: using a local reference to set an object as an
instance variable: 

NSNumber* value1 = [[NSNumber alloc] initWithFloat:8.75];


[self setTotal:value1];
NSNumber* value2 = [NSNumber numberWithFloat:14.78];
[self setTotal:value2];
[value1 release];

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");

Unlike subclasses, categories can't add instance variables. You can,


however, use categories to override existing methods in classes, but
you should do so very carefully. Remember, when you make changes
to a class using a category, it affects all instances of that class
throughout the application.
References

 Apple Inc. Apple Developer Connection


http://developer.apple.com

 Learn Objective-C

http://cocoadevcentral.com/d/learn_o
bjectivec/

You might also like