Objective-C
Day 1 - Session 1
Vitor Carreira
ESTG/IPL July 24-28, 2012 Leiria, Portugal
Quick Introduction
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
Requirements
Requirements for this session
Moderate knowledge of the C programming language Basic knowledge of Object Oriented Programming concepts (instance vs class, encapsulation, inheritance and polymorphism)
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
Why Objective-C?
Selected as the main language by NeXT
developing Mac OS X (2001) using Objective-C legacy :) (company founded by Steve Jobs) to develop the NeXTStep OS
In 1996, Apple acquires NeXT and starts Objective-C is not a choice but rather a
July 24-28, 2012 iOS Game Development - International Summer School, ESTG/IPL 4
Syntax
Objective-C 2.0 is a superset of the C99 standard. All features of the C language are preserved
Case sensitive, strongly typed, every variable should be declared before used, separates function declaration (header le) from function implementation (implementation le), vars declared inside a function are local, pass by reference using pointers, etc Same set of operators and control ow structures Extensions to the C language are identied with the @ symbol New le extensions: .m (implementation le), .h (header le) Var names: lowerCamelCase Function names: UpperCamelCase
iOS Game Development - International Summer School, ESTG/IPL 5
New features
July 24-28, 2012
Data value types
Value types: char, int, oat, double Modiers: unsigned, short, long By default, are integers are signed Enumerations: keyword enum Structures: keyword struct
July 24-28, 2012 iOS Game Development - International Summer School, ESTG/IPL 6
Pre-processor
All lines that start with # are executed by the pre-processor. Just to recap:
#dene - denes a macro #if, #else, #endif - conditional includes code or macros #import - includes the le only once (should be used instead of #include)
#import <Foundation/Foundation.h> #define PI 3.14159265 int main(int argc, const char * argv[]) { #if DEBUG NSLog(@"Debug mode on"); #endif NSLog(@"Hello, PI (%g)!", PI); return 0; }
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
Hello World
main.m
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int igdDays = 5; NSLog(@"Hello, iGD - Welcome aboard to %d days of fun!", igdDays); } return 0; }
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
Demo time Lets try it on Xcode
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
Classes
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
10
Classes 1/2
In Objective-C, a class has two parts:
@interface - part where the class interface is declared (public instance/class methods and public properties). The public interface must be placed on an header le (.h) @implementation - part where the methods are implemented. The implementation must be placed on a code le (.m)
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
11
Classes 2/2
Some conventions:
Class name: UpperCamelCase Members and properties: lowerCamelCase
Objective-C doesnt have namespaces. It is recommended to use a prex of 2 to 4 letters to avoid collisions between class names Some prexes are already reserved: NS, IB, CG, etc
iOS Game Development - International Summer School, ESTG/IPL 12
July 24-28, 2012
Syntax
Interface part 1/3
@interface ClassName : ParentClassName { // Optional public or protected ivars } // Public property declaration // Public methods declaration @end
Example (ComplexNumber.h)
@interface ComplexNumber : NSObject - (double)modulus; - (void)setRadius:(double)aRadius phase:(double)aPhase; - (void)debug; @end
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
13
Interface part 2/3
Every class should be a direct or indirect descendant of NSObject Instance variables (ivars) that are protected or public (not recommended) are declared between {} If no scope is given, ivars are @protected. Available scopes: @public, @protected, @private and @package Syntax to declare an instance variable: Type instanceVarName;
iOS Game Development - International Summer School, ESTG/IPL 14
July 24-28, 2012
Interface part 3/3
Method declaration: Method type:
MethodType (ReturnType)namePart1: (Type)param1 namePart2: (Type)param2, ...;
Use the - sign for instance methods Use the + sign for class methods
iOS Game Development - International Summer School, ESTG/IPL 15
July 24-28, 2012
Method overloading
Method overloading is not supported
Methods with the same name but different parameter types
How the name of the method is represented?
// Name = modulus - (double)modulus; // Name = debug - (void)debug; // Name = setRadius:phase: - (void)setRadius:(double)aRadius phase:(double)aPhase; // Name = setRadius: - (void)setRadius:(double)aRadius
July 24-28, 2012 iOS Game Development - International Summer School, ESTG/IPL 16
Implementation part 1/2
Syntax
@implementation ClassName { // Optional private ivars } // Public or private methods implementation @end
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
17
Implementation part 2/2
Example (ComplexNumber.m)
#import ComplexNumber.h @implementation ComplexNumber { double realPart; double imaginaryPart; } - (double)modulus { return sqrt(realPart*realPart + imaginaryPart*imaginaryPart); } - (void)setRadius:(double)aRadius phase:(double)aPhase { realPart = aRadius * cos(aPhase); imaginaryPart = aRadius * sin(aPhase); } - (void)debug { NSLog(@"%g + %gi", realPart, imaginaryPart); } @end
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
18
Putting all together main.m
#import <Foundation/Foundation.h> #import "ComplexNumber.h" int main(int argc, const char * argv[]) { ComplexNumber *c1 = [[ComplexNumber alloc] init]; [c1 debug]; [c1 setRadius:5 phase:M_PI_4]; [c1 debug]; return 0; }
[[ComplexNumber alloc] init] Allocates e initializes a new instance of ComplexNumber An object is always represented by a pointer
July 24-28, 2012 iOS Game Development - International Summer School, ESTG/IPL 19
Method invocation
In Objective-C, invoking a method consists en sending a message to it. General syntax: [receptor message] Instance methods (the instance is the receptor):
[instance methodName] [instance methodName:param1] [instance methodNamePart1:param1 part2:param2]
Class methods: the same syntax but the receptor is the class name (e.g. [ComplexNumber alloc])
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
20
Getters and setters 1/3
By convention:
The getter method name is equal to the ivar.The get prex is not used The setter has the following name:
- (void)set<IVarName>:(IVarType)value
@interface ComplexNumber : NSObject - (double)realPart; // Getter - (void)setRealPart:(double)value; // Setter - (double)imaginaryPart; // Getter - (void)setImaginaryPart:(double)value; // Setter (...) @end
July 24-28, 2012 iOS Game Development - International Summer School, ESTG/IPL 21
Getters and setters 2/3
@implementation ComplexNumber { double realPart; double imaginaryPart; } - (double)realPart { return realPart; } - (void)setRealPart:(double)value { realPart = value; } - (double)imaginaryPart { return imaginaryPart; } - (void)setImaginaryPart:(double)value { imaginaryPart = value; } (...) @end July 24-28, 2012 iOS Game Development - International Summer School, ESTG/IPL 22
Getters and setters 3/3
int main(int argc, const char * argv[]) { Not ComplexNumber *c1 = [[ComplexNumber alloc] init];
cool!
[c1 setRealPart:3]; [c1 setImaginaryPart:2]; double newValue = [c1 realPart] * 3; [c1 setRealPart: newValue]; [c1 setImaginaryPart:[c1 imaginaryPart] * 3]; [c1 debug]; return 0; }
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
23
Properties 1/4
Objective-C 2.0 has introduced a new syntax to implement getters and setters called dot syntax Invoking getters and setters becomes familiar. Some examples:
int age = [person age]; int age = person.age; // getter dot syntax [person setAge: 39]; person.age = 39; // setter dot syntax [[person father] setAge: 68]; person.father.age = 68; // setter dot syntax
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
24
Properties 2/4
Declaring a property:
On the interface part use the @property directive
@property (optional attributes) PropertyType propertyName
@interface ComplexNumber : NSObject @property double realPart; @property double imaginaryPart; - (double)modulus; - (void)setRadius:(double)aRadius phase:(double)aPhase; - (void)debug; @end
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
25
Properties 3/4
Synthesizing a property:
On the implementation part use the @synthesize directive
@synthesize propertyName[=optional_ivarname];
By default, @synthesize follows the same conventions for getters and setters and injects the following pair of methods: -(void)setIVarName:(Type)value; -(Type)varIName;
@implementation ComplexNumber @synthesize realPart; @synthesize imaginaryPart;
(...)
@end
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
26
Properties 4/4
#import "ComplexNumber.h" int main(int argc, const char * argv[]) { ComplexNumber *c1 = [[ComplexNumber alloc] init]; c1.realPart = 3; c1.imaginaryPart = 2; [c1 debug]; c1.realPart *= 3; c1.imaginaryPart += 2; [c1 debug]; return 0; }
Easier to type. Easier to remember
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
27
Inheritance 1/2
Objective-C only supports single inheritance There is no such thing as a protected method To redene a parent method you just have to provide the new implementation (keeping the method signature) The keyword self is a reference for the current instance The keyword super refers to the parent of the current instance
iOS Game Development - International Summer School, ESTG/IPL 28
July 24-28, 2012
Inheritance 2/2
In Objective-C method invocation follows the dynamic binding mechanism. One a message is sent to a receptor:
The runtime checks if the receptor implements the method invoked. If the method is founded it is executed. If the method is not founded, the message is sent to the receptors parent
The receptor hierarchy is traversed until one of the following conditions is veried:
The method is founded and invoked The method is not found when reaching the hierarchy top and an exception is thrown
iOS Game Development - International Summer School, ESTG/IPL 29
July 24-28, 2012
Some Language Considerations
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
30
Exceptions 1/3
Exception handling is similar to C# or Java
@try { [f noSuchMethod]; } @catch (NSException *exception) { NSLog(@Caught %@%@, [exception name], [exception reason]); } @finally { NSLog(@Always called); }
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
31
Exceptions 2/3
You can have multiple @catch blocks to catch different types of exceptions Use @throw to throw an exception
If inside a @catch block the exception instance can be omitted @throw; // Re throws the exception caught
NSException is the base class for all exceptions
The runtime doesnt impose this kind of check
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
32
Exceptions 3/3
In languages like C# or Java, exceptions is fairly commonplace and used intensively to signal errors that affect the execution ow Exceptions are resource-intensive in Objective-C.You should not use exceptions for general ow-control, or simply to signify errors. Instead you should use the return value of a method or function to indicate that an error has occurred, and provide information about the problem in an error object
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
Very important
error:(NSError **)outError;
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
33
BOOL vs bool
Objective-C 1.0 didnt have a boolean data type So the type BOOL was introduced to the language with the macros YES (true) and NO (false) Objective-C 2.0 is a superset of C99 so it also has the boolean type bool that is almost never used due the legacy code
BOOL isLessonComplete = NO; bool newButSeldomUsed = true;
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
34
Static vs dynamic typing
Static typing - the data type is always
specied
ComplexNumber *aNumber;
Dynamic typing - the data type is not
id anyObject;
specied. So the variable can represent any object (equivalent to the void * in C)
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
35
Nil instance
The keyword nil represents a null instance. It can be used:
To assign an null object to a variable
aComplexNumber = nil;
As part of a condition
if (aComplexNumber == nil) or if (!aComplexNumber)
As a method argument:
[slider setTarget: nil];
As a receptor (message is ignored and returns 0)
aComplexNumber = nil; value = [aComplexNumber modulus];
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
36
Selectors 1/2
SEL is a data type called selector that represents a method (similar to a function pointer) A selector is declared using the methods full name. The following method
- (void)setRadius:(double)r phase:(double)p
Could be represented with the following selector:
SEL setAll = @selector(setRadius:phase:);
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
37
Selectors 2/2
The NSObject class provides several methods that work with selectors (e.g. respondsToSelector, performSelector, etc). For example:
id receiver = self.target; SEL sel = self.action; if ([receiver respondsToSelector:sel]) { [receiver performSelector:sel withObject:self]; }
July 24-28, 2012 iOS Game Development - International Summer School, ESTG/IPL 38
Allocation and Initialization
There is no such thing as constructors
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
39
Allocation and initialization 1/5
AClass *anObject = [[AClass alloc] init];
Two steps are required to instantiate an class:
1. Allocate memory for the instance. NSObject provides two methods for that: alloc e allocWithZone
When memory is allocated all ivars are set to zero (objects are set to nil)
2. Initialize the instance with the desired values. The class is responsible to provide proper initializers to initialize the instance. By convention (this is very important) all initializers methods must start with init
July 24-28, 2012
All classes that have instance variables should provide at least one initializer
iOS Game Development - International Summer School, ESTG/IPL
40
Allocation and initialization 2/5
-(id)init {...}
An initializer must initialize all ivars of the receptor and returns its own instance Exceptionally a different instance or even nil can be returned by an initializer. So the value returned by the initializer should always be kept By convention, the initializer should be called only once (very important for memory management)
iOS Game Development - International Summer School, ESTG/IPL 41
July 24-28, 2012
Allocation and initialization 2/5
Incorrect
AClass *anObject = [AClass alloc]; [anObject init]; [anObject someMethod];
Correct
AClass *anObject = [AClass alloc]; anObject = [anObject init]; [anObject someMethod];
Typical code
AClass *anObject = [[AClass alloc] init]; [anObject someMethod];
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
42
Allocation and initialization 4/5
Rules to implement an initializer
By convention, the method should start with the name init The method must return id If the class has more than one initializer it is required to state which one is the designated initializer. This is the initializer that all the other initializers should invoke The designated initializer is the only one to invoke the parent initializer You must assign to self the result of calling the designated or parent initializer.You should check if the result is nil (exceptionally an initializer can return nil or an different instance of the one currently allocated) You should not use getters and setters to initialize ivars The initializer must always return self (or nil if an error occurs)
iOS Game Development - International Summer School, ESTG/IPL 43
July 24-28, 2012
Example
Allocation and initialization 5/5
- (id)init { // Calls the designated initializer return [self initWithReal:0 imaginary:0]; } // This is my designated initializer // A general rule of thumb (although not always the case) is that the designated initializer is the initializer with the most parameters. - (id)initWithReal:(double)real imaginary:(double)imaginary { // Calls the parent initializer self = [super init]; if (self) { realPart = real; imaginaryPart = imaginary; } return self; } - (id)initWithRadius:(double)aRadius phase:(double)aPhase { // Calls the designated initializer return [self initWithReal:aRadius * cos(aPhase) imaginary:aRadius * sin(aPhase)]; }
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
44
Some classes combine allocation and
initialization in a single step
Combining allocation and initialization
constructors and usually start with the name of the class
This methods are called convenience Examples from NSString:
+ (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc; + (id)stringWithFormat:(NSString *)format, ...;
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
45
Before moving to the next session. Any questions?
July 24-28, 2012
iOS Game Development - International Summer School, ESTG/IPL
46