Professional Documents
Culture Documents
Day 1 - Session 1
Vitor Carreira
ESTG/IPL July 24-28, 2012 Leiria, Portugal
Quick Introduction
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)
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
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; }
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; }
Classes
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)
11
Classes 2/2
Some conventions:
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
Syntax
@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
13
Use the - sign for instance methods Use the + sign for class methods
iOS Game Development - International Summer School, ESTG/IPL 15
Method overloading
Method overloading is not supported
17
18
[[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])
20
cool!
[c1 setRealPart:3]; [c1 setImaginaryPart:2]; double newValue = [c1 realPart] * 3; [c1 setRealPart: newValue]; [c1 setImaginaryPart:[c1 imaginaryPart] * 3]; [c1 debug]; return 0; }
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
24
Properties 2/4
Declaring a property:
@interface ComplexNumber : NSObject @property double realPart; @property double imaginaryPart; - (double)modulus; - (void)setRadius:(double)aRadius phase:(double)aPhase; - (void)debug; @end
25
Properties 3/4
Synthesizing a property:
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
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; }
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
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
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); }
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
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;
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;
34
specied. So the variable can represent any object (equivalent to the void * in C)
35
Nil instance
As part of a condition
if (aComplexNumber == nil) or if (!aComplexNumber)
As a method argument:
[slider setTarget: nil];
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
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
39
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
All classes that have instance variables should provide at least one initializer
40
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
Correct
AClass *anObject = [AClass alloc]; anObject = [anObject init]; [anObject someMethod];
Typical code
AClass *anObject = [[AClass alloc] init]; [anObject someMethod];
42
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
Example
- (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)]; }
44
45
46