Introduc)on to Objec)ve-‐C
Jussi Pohjolainen Tampere University of Applied Sciences
QUICKSTART
Background
• Objec)ve-‐C is layered on top of the C – language – Based on SmallTalk-‐80 – Designed in early 1980s
• NeXT SoLware licensed Objec)ve-‐C in 1988 • Apple Computer acquired NeXT in 1996 • Today: na)ve language for developing Mac OS X -‐ and iPhone -‐ apps
Class Declara)on: MyPoint.h
Class Implementa)on: MyPoint.m
Test the Class: main.m
Simple makefile MyPoint : MyPoint.m main.m
clang -fno-objc-arc -framework foundation MyPoint.m main.m -o MyPoint
run :
./MyPoint
clean :
rm MyPoint
Compiling and Running TB308POHJUS-L-2:point pohjus$ ls -al
total 32
drwxr-xr-x 6 pohjus staff 204 18 Tou 15:32 .
drwxr-xr-x 3 pohjus staff 102 18 Tou 14:52 ..
-rw-r--r--@ 1 pohjus staff 196 18 Tou 15:25 MyPoint.h
-rw-r--r--@ 1 pohjus staff 268 18 Tou 15:23 MyPoint.m
-rw-r--r--@ 1 pohjus staff 339 18 Tou 15:25 main.m
-rw-r--r--@ 1 pohjus staff 120 18 Tou 15:14 makefile
TB308POHJUS-L-2:point pohjus$ make
clang -fno-objc-arc -framework foundation MyPoint.m main.m -o MyPoint
TB308POHJUS-L-2:point pohjus$ make run
./MyPoint
2009-05-18 15:32:46.339 MyPoint[8725:807] X = 0 and Y = 0
2009-05-18 15:32:46.341 MyPoint[8725:807] X = 8 and Y = 7
TB308POHJUS-L-2:point pohjus$
Instan)a)ng an Object
// Declare a pointer to the object
MyPoint* point;
// Allocate memory for the object
point = [MyPoint alloc];
// Initialize the object
point = [point init];
Instan)a)ng an Object: One Liner
// Allocate and initialize the object
MyPoint* point1 = [[MyPoint alloc] init];
Messages (Methods)
- (void) setX: (int) n;!
method type: + = class method -‐ = object method
return type selector name
argument type
argument name
Messages, with Two Arguments
Declara=on - (void) setXAndY: (int) x: (int) y Usage [object setXAndY: 5: 6]; Declara=on, be@er way - (void) setX: (int) x andY: (int) y Usage [object setX: 5 andY: 6];
EXERCISES
MEMORY MANAGEMENT AND OBJECT LIFECYCLE
Memory Handling in General
• When allocate something it must be released – Memory consump)on
• In Java, garbage collector takes care of the release. Separate thread looking for objects that can be released
• In Obj-‐C and C/C++, programmer is responsible about the release.
About Pointers
• int a = 5; – Holds one integer value – The integer is stored in some memory address
• Where? – You can get the memory address by using & in front of the variable: &a
Example of Memory Address int main(int argc, char *argv[]) { int a = 5; // prints 5 NSLog(@"%i", a); // prints something like 0x7fff5fbff9cc NSLog(@"%p", &a); return 0; }
Pointers
• Pointer is a variable that stores memory address
• int a; – holds integer variable
• int* b; – holds memory address that points to integer value
• int* b = &a; – Now b has the memory address of a
Example about Pointers #import "MyPoint.h" int main(int argc, char *argv[]) { int a = 5; // Store a's memory address to variable b int *b = &a; // prints 5 NSLog(@"%i", a); // prints something like 0x7fff5fbff9cc NSLog(@"%p", &a); // prints something like 0x7fff5fbff9cc NSLog(@"%p", b); // prints 5 NSLog(@"%i", *b); return 0; }
What is the result now? int main(int argc, char *argv[]) { int a = 5; // Store a's memory address to variable b int *b = &a; if(b == &a) { NSLog(@"Do we go here?"); } if(*b == a) { NSLog(@"What about here?"); } return 0; }
What is the result now? int main(int argc, char *argv[]) { int a = 5; int *b = &a; *b = 10; NSLog(@"%i", a); return 0; }
Memory Areas
• Memory can be divided into three categories 1. Global or sta)c 2. Stack 3. Heap
Sta)c
• When something is in sta)c memory, it's there all the )me when app is running
• So when star)ng the app, the memory is allocated an when the app closes, the memory is deallocated
• The variable is stored in the same memory address all the )me.
Example of Sta)c Memory int thisIsStoredInStaticMemory = 5;
int main(int argc, char *argv[])
{
static int thisIsAlsoStoredInStaticMemory = 10;
NSLog(@"My number = %i", thisIsStoredInStaticMemory);
NSLog(@"My number = %i", thisIsAlsoStoredInStaticMemory);
return 0;
}
Stack -‐ Memory
• Stack – memoryarea is usually small • If you put too much "stuff" into stack, you might get stack overflow
• Local variables are stored in stack! • Variables are released when out of scope
Example of Stack Memory int main(int argc, char *argv[]) { int stack1 = 3; NSLog(@"My number = %i", stack1); if(YES) { int stack2 = 4; NSLog(@"My number = %i", stack2); // stack2 is released from memory now. } // stack1 is released from memory now. return 0; }
Example of Stack Memory int main(int argc, char *argv[]) { if(YES) { int stack2 = 4; } // Does this work? NSLog(@"My number = %i", stack2); return 0; }
Heap -‐ Memory
• Heap – memory is the large memory area where almost all of the objects go.
• Programmer is responsible for releasing the objects!
Example of Heap -‐ memory #import "MyPoint.h" int main(int argc, char *argv[]) { MyPoint* point = [MyPoint alloc]; //... [point release]; return 0; }
Crea)ng a Object
• The crea)on of an object is done in two parts • 1) Alloca)ng memory – MyPoint* point = [MyPoint alloc];
• 2) Ini)alize object state – point = [point init];
• Combined – MyPoint* point = [[MyPoint alloc] init];
• ó – MyPoint* point = [MyPoint new];
What happens in Memory?
• What happens in here? – MyPoint* p = [MyPoint alloc];
• Two things! – MyPoint* p; – p = [MyPoint alloc];
• p is in stack – memory! • MyPoint object is in heap memory!
Problem? #import "MyPoint.h" int main(int argc, char *argv[]) { if(YES) { MyPoint* point = [MyPoint alloc]; } [point release]; return 0; }
Problem? #import "MyPoint.h" int main(int argc, char *argv[]) { MyPoint* point = [MyPoint alloc]; point = [MyPoint alloc]; [point release]; return 0; }
init-‐method? • init-‐method is implemented in NSObject • You can however implement your own init-‐method
- (id) initWithName: (NSString*) aName { if(self = [super init]) { name = aName; } return self; }
Other init-‐methods
• Like in Java and C++, one can have mul)ple constructors
• In Obj-‐C, one can have mul)ple init-‐methods - (id) init - (id) initWithX: (int) aX; - (id) initWithX: (int) aX andY: (int) aY
Deallocing Object and Reference Count
• Rules about reference coun=ng – When object is created its reference count is set to 1 – Incremen)ng the reference count:
• [point retain]; – Decreasing reference count
• [point release]; – When reference count reaches to 0, dealloca=ng occurs
• ARC will save you from this!
Reference Count Example #import <Foundation/Foundation.h>
@interface Cat : NSObject
{
}
- (void) printMyRetainCount;
@end
@implementation Cat
- (void) printMyRetainCount
{
NSLog(@"Retain count = %i", [self retainCount]);
}
@end
Reference Count Example int main(int argc, char *argv[])
{
Cat* myCat = [[Cat alloc] init];
[myCat printMyRetainCount]; // Retain count = 1
Cat* reference = myCat;
[reference retain];
[myCat printMyRetainCount]; // Retain count = 2
[myCat release];
[myCat printMyRetainCount]; // Retain count = 1
[myCat release]; // Deallocation
return 0;
}
dealloc
• You can implement a dealloc method
(void) dealloc
{
// Some code
[super dealloc];
}
Reference Count Example #import <Foundation/Foundation.h>
@interface Cat : NSObject
{
NSString* name;
}
- (void) setName: (NSString *) theName
@end
@implementation Cat
- (void) setName: (NSString *) theName
{
name = theName;
}
@end
int main(int argc, char *argv[])
{
....
Cat* mirri = [[Cat alloc] init];
[mirri setName: someName];
// What happens now?
[someName release];
}
Since reference count is 0, dealloca)on occurs. This means, that the Cat does not have a name
anymore.
Reference Count Example #import <Foundation/Foundation.h>
@interface Cat : NSObject
{
NSString* name;
}
- (void) setName: (NSString *) theName
@end
@implementation Cat
- (void) setName: (NSString *) theName
{
[name release];
name = theName;
[name retain];
}
@end
int main(int argc, char *argv[])
{
....
Cat* mirri = [[Cat alloc] init];
[mirri setName: someName];
// What happens now?
[someName release];
}
Since reference count is 1, dealloca)on does not occur and the Cat s)ll
has it's name.
Copying a Object
- (void)setName:(NSString *)theName
}
[name release];
name = [theName copy];
}
Autorelease Pool
• Every Founda)on program must set up autorelease pool for the Founda)on objects
• Pool keeps track of your objects for later release – NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
– ... – [pool drain];
Method Names
• If method name includes alloc or copy, it returns a object that must be released – // Must be released – NSObject* object = [[NSObject alloc] init]; – // Must be released – NSObject* copy = [object copy]; – // Do not have to release – NSMutableString* string = [NSMutableString string];
• The above string is released in Autorelease Pool!
Problem // Programmer A code
[[someObject giveCat] eat];
// Programmer B code
- (Cat*) giveCat
{
// Must be released!
Cat* myCat = [[Cat alloc] init];
// But where? Should the programmer who calls this method be
// responsible for deallocation of the Cat? How does the programmer
// know this?
return myCat;
}
..
Solu)on // Programmer A code [[someObject giveCat] eat]; // Programmer B code - (Cat*) giveCat {
// Must be released! Cat* myCat = [[Cat alloc] init]; // But where? When autopool is drained! [myCat autorelease]; return myCat; }
Delayed Release
• Autorelease means "send release message later".
• Release message is sent when Autorelease Pool is released
• Autorelease Pool is created and released in UIKit programs automa=cally! – Pool is created at the beginning of an event cycle – Pool is released at the end of an event cycle
Autorelease Pools
App Loaded Wait for Event Handle event Exit app
Event loop
Pool created
Pool released
Autorelease Pool Usage // Method
- (Cat*) giveCat
{
// Must be released!
Cat* myCat = [[Cat alloc] init];
// But where? When autopool is drained!
[myCat autorelease];
return myCat;
}
// Usage
Cat* someCat = [object giveCat];
// someCat will be released in some time, so if you want to hold it, use
// retain
[someCat retain];
Rules
• If method name contains "alloc", "new" or "copy", you must remember to use release or autorelease – Example: alloc, newObject, mutableCopy
• If you retain something, you must use release or autorelease
• Instance Variables: retain or copy • autorelease means "send release later"
Cat.h #import <Foundation/Foundation.h> @interface Cat : NSObject { @private NSString* name; } - (id) initWithName: (NSString*) aName; - (void) setName: (NSString*) aName; - (NSString*) getName; - (void) dealloc; @end
Cat.m #import "Cat.h" @implementation Cat - (id) initWithName: (NSString*) aName { if(self = [super init]) { [self setName: aName]; } return self; } - (NSString*) getName { return name; }
- (void) setName: (NSString*) aName { if(aName != name) { [name release]; name = aName; [name retain]; } } - (void) dealloc { [name release]; [super dealloc]; } @end
main.m #import "Cat.h" int main(int argc, char *argv[]) { NSAutoreleasePool *pool =
[[NSAutoreleasePool alloc] init]; // Create the string NSString* catName = [[NSString
alloc] initWithString: @"Jack"]; // Create cat with the string Cat* cat = [[Cat alloc]
initWithName: catName]; // Just testing. This does not
deallocate catName! [catName release];
// Get the name NSString* name = [cat getName]; // Print the name NSLog(name); // Release name and cat [cat release]; [pool drain]; return 0; }
MANAGING MEMORY WITH ARC ARC to the rescue!
ARC?
• ARC (Automa=c Reference Coun=ng) – Compiler does automa/c reference coun/ng by examining the source code and then add the retain and release messages to objects
• Not garbage collec)on, no background process of dealloca)on of objects!
• Inserts retain and release statements based on some fixed rules
• OS X 10.7 and iOS 5 for all features
Object lose owners // Scenario 1 Person* jack = [[Person alloc] init]; jack = [[Person alloc] init]; // Scenario 2 Person* tina = [[Person alloc] init]; tina = nil;
// Scenario 3 if(yes) { Person* dave = [[Person alloc] init]; }
Some Fixed rules
• If object is allocated and local to method, release statement is added near the end of that method
• If allocated object is class a@ribute, release is added to dealloc
• If the object is return value, it gets an autorelease statement
Guidelines
• Don’t call! – retain, release, retainCount, autorelease or dealloc
• You must use @autoreleasepool syntax • You must enable ARC – clang -fobjc-arc -framework foundation Car.m Motor.m main.m -o App
makefile MyPoint : Car.m Motor.m main.m
clang -fobjc-arc -framework foundation Car.m Motor.m main.m -o App
run :
./App
clean :
rm App
main.m
motor.h
motor.m
car.h
car.m
PROPERTIES
Objec)ve-‐C 2.0: @property
Objec)ve-‐C 2.0: @synthesize
Objec)ve-‐C 2.0: Dot Syntax
Autosynthesize
Autosynthesize
Property Declara)on Aoributes: Writability
• You can decorate a property with aoributes, example: – @property (readonly) int x;
• readwrite – Indicates that the property is read/write. Default
• readonly – Only read – Generates only geoer method
Seoer Seman)cs • assign – Simple seoer. Default.
• weak – Non-‐owning rela)onship with an object – If object is deallocated, the property is set to nil
• strong – Owning rela)onship with an object
• copy – Specifies that a copy of the object should be used for assignment
Seoer Seman)cs Examples // assign
property = newValue;
// copy
if (property != newValue)
{
[property release];
property = [newValue copy];
}
Atomicity
• nonatomic – Specifies that accessor are non-‐atomic.
• Proper)es are atomic by default: – [_internal lock]; – id result = [[value retain] autorelease]; – [_internal unlock]; – return id;
Car.h
Motor.h
Main.m
Change! Car.h
STRINGS
About Strings
• C String – char * // Array of characters
• NSString – Object, that holds array of Unicode characters – Is immutable, contents cannot be changed aLerwards!
• NSMutableString – String that can be modified aLerwards
Crea)ng Strings // Simple way
NSString *temp1 = @"Hello World!";
// Appending, notice that this produces new string
NSString *beginning = @"beginning";
NSString *alphaAndOmega = [beginning stringByAppendingString:@" and end"];
Formapng
• Formapng – NSString *string1 = [NSString stringWithFormat:@"A
string: %@, a float: %1.2f", @"string", 31415.9265];
– // string1 is "A string: string, a float: 31415.93"
• Format Specifiers? – http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265-SW1
NSString methods
• See: – http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
NSMutableString methods
• NSMutableString inherites NSString • With NSMutableString you can modify the string with these methods
– appendFormat:
– appendString:
– deleteCharactersInRange:
– insertString:atIndex:
– replaceCharactersInRange:withString:
– replaceOccurrencesOfString:withString:options:range:
– setString:
PROTOCOLS
Protocols?
• Compared to Java, protocols are interfaces • You define methods that some object must implement
Using Protocols // MyProtocolName.h
// Notice that the protocol inherites NSObject
// protocol!
@protocol MyProtocolName <NSObject> //Method declarations go here
@end
// MyObject
@interface Class: NSObject <MyProtocolName>
Protocol as Variable • In Java – MyInterface object = new MyObject();
• In Obj-‐C – id<MyProtocolName> object = [[MyObject alloc] init];
• As a method argument – (void) doSomethingWithThisObject: (id<MyProtocolName>) aObject
• ID is a predefined pointer type for an arbitrary object
FOUNDATION CLASSES
NSObject
• NSObject is the root class of Most Obj-‐C classes
• Crea)ng, copying, dealloca)ng objects
Collec)ons
• Array: Ordered Collec/ons • Dic)onary: Collec/ons of Keys and Values • Set: Unordered Collec/ons of Objects • Counted Sets: Unordered Collec/on of Indis/nct Objects
• Enumera)on: Traversing a Collec/on's Elements
• Mutable and immutable versions!
Other Classes
• NSNumber, wrapper for standard number types
• NSDate, NSCalendarDate