1. Computer Science Large Practical:
Crash Course in Objective-C
Stephen Gilmore
School of Informatics
Friday 12th October, 2012
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 1 / 33
2. Acknowledgements
We are following Appendix C of
Beginning iOS 5 Application
Development
Wei-Meng Lee
John Wiley & Sons, Inc.
2012
www.it-ebooks.info
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 2 / 33
3. Objective-C sources
Objective-C source code files are contained in two types of files:
.h header files
.m implementation files
Thus a project could contain a file called SomeClass.h
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 3 / 33
4. Directives
If you observe the content of the SomeClass.h file, you will notice that at
the top of the file is typically an #import statement:
#import <Foundation/Foundation.h>
@interface SomeClass : NSObject {
}
@end
The #import statement is known as a preprocessor directive.
(NS stands for ”NeXTStep”, the project which created Objective-C.)
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 4 / 33
5. Importing your own header files
To import a header file from within your project, you use the quote
characters, as in the case of the SomeClass.m file:
#import "SomeClass.h"
@implementation SomeClass
@end
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 5 / 33
6. Classes
To declare a class, you use the @interface compiler directive, like this:
@interface SomeClass : NSObject {
}
This is done in the header file (.h), and the class declaration contains no
implementation. The preceding code declares a class named SomeClass,
and this class inherits from the base class named NSObject.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 6 / 33
7. Classes
To implement a class declared in the header file, you use the
@implementation compiler directive, like this:
#import "SomeClass.h"
@implementation SomeClass
@end
This is done in a separate file from the header file. In Objective-C, you
define your class in an .m file.
Note
Note that the class definition ends with the @end compiler directive.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 7 / 33
8. Mutual recursion
If your class references another class defined in another file, you need
to import the header file of that file before you can use it.
To prevent circular inclusion, Objective-C uses the @class compiler
directive as a forward declaration to inform the compiler that the class
you specified is a valid class.
You usually use the @class compiler directive in the header file; and in
the implementation file, you can use the @import compiler directive
to tell the compiler more about the content of the class you are using.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 8 / 33
9. Mutual recursion example
// SomeClass.h
#import <Foundation/Foundation.h>
@class AnotherClass; // forward declaration
@interface SomeClass : NSObject {
// an object from AnotherClass
AnotherClass *anotherClass;
}
@end
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 9 / 33
10. Mutual recursion example
// SomeClass.h
#import <Foundation/Foundation.h>
@class AnotherClass; // forward declaration
@interface SomeClass : NSObject {
// an object from AnotherClass
AnotherClass *anotherClass;
}
@end
// AnotherClass.h
#import <Foundation/Foundation.h>
@class SomeClass; // forward declaration
@interface AnotherClass : NSObject {
SomeClass *someClass; // using an instance of SomeClass
}
@end
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 9 / 33
11. Class instantiation
To create an instance of a class, you typically use the alloc keyword to
allocate memory for the object and then return it to a variable of the class
type:
SomeClass *someClass = [SomeClass alloc];
In Objective-C, you need to prefix an object name with the * character
when you declare an object.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 10 / 33
12. Primitive types
If you are declaring a variable of primitive type (such as float, int, CGRect,
NSInteger, and so on), the * character is not required. Here are some
examples:
CGRect frame; // CGRect is a structure
int number; // int is a primitive type
NSString *str; // NSString is a class
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 11 / 33
13. The id type
Besides specifying the returning class type, you can also use the id type,
like this:
id someClass = [SomeClass alloc];
id str;
The id type means that the variable can refer to any type of object; hence,
the * is implied.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 12 / 33
14. Fields
Fields are the data members of objects. For example, the following code
shows that SomeClass has three fields — anotherClass, rate, and name:
// SomeClass.h
#import <Foundation/Foundation.h>
@class AnotherClass; // forward declaration
@interface SomeClass : NSObject {
// an object from AnotherClass
AnotherClass *anotherClass;
float rate;
NSString *name;
}
@end
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 13 / 33
15. Access Privileges
By default, the access privilege of all fields is @protected. However, the
access privilege can also be @public or @private. The following list
describes the various access privileges:
@private Visible only to the class that declares it
@public Visible to all classes
@protected Visible to the class that declares it and inheriting classes
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 14 / 33
16. Public fields
To make the rate and name visible outside the class, modify the
SomeClass.h file by adding the @public compiler directive:
#import <Foundation/Foundation.h>
@class AnotherClass; // forward declaration
@interface SomeClass : NSObject {
AnotherClass *anotherClass;
@public
float rate;
@public
NSString *name;
}
@end
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 15 / 33
17. Public fields
We can now access the fields ”rate” and ”name” directly (using the ”->”
operator).
SomeClass *someClass = [SomeClass alloc];
someClass->rate = 5; // rate is declared public
someClass->name = @"Wei-Meng Lee"; // name is public
Although we can access the fields directly, doing so goes against the
design principles of object-oriented programming’s rule of encapsulation.
A better way is to encapsulate the two fields we want to expose in
properties, as we will see later.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 16 / 33
18. Methods
Objective-C supports two types of methods: instance methods and class
methods.
Instance methods can only be called using an instance of the class;
and they are prefixed with the minus sign (−) character.
Class methods can be invoked directly using the class name and do
not need an instance of the class in order to work. Class methods are
prefixed with the plus sign (+) character.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 17 / 33
20. Methods in implementations (1/2)
#import "SomeClass.h"
@implementation SomeClass
// instance methods
-(void) doSomething {
// implementation here
}
-(void) doSomething:(NSString *) str {
// implementation here
}
-(void) doSomething:(NSString *) str withAnotherPara:(float)
value {
// implementation here
}
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 19 / 33
21. Methods in implementations (2/2)
// class method
+(void) alsoDoSomething {
// implementation here
}
@end
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 20 / 33
22. Invoking methods
To invoke the three instance methods, you first need to create an instance
of the class and then call them using the instance created:
SomeClass *someClass = [SomeClass alloc];
[someClass doSomething];
[someClass doSomething:@"some text"];
[someClass doSomething:@"some text" withAnotherPara:9.0f];
Class methods can be called directly using the class name, as the following
shows:
[SomeClass alsoDoSomething];
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 21 / 33
23. Message Sending (Calling Methods)
Strictly speaking, in Objective-C you do not call a method; rather,
you send a message to an object.
The message to be passed to an object is resolved during runtime and
is not enforced at compile time.
This is why the compiler does not stop you from running your
program even though you may have misspelled the method name.
It does warn you that the target object may not respond to your
message, though, because the target object will simply ignore the
message (and in most situations result in a runtime exception).
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 22 / 33
24. Message Sending (Calling Methods)
Strictly speaking, in Objective-C you do not call a method; rather,
you send a message to an object.
The message to be passed to an object is resolved during runtime and
is not enforced at compile time.
This is why the compiler does not stop you from running your
program even though you may have misspelled the method name.
It does warn you that the target object may not respond to your
message, though, because the target object will simply ignore the
message (and in most situations result in a runtime exception).
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 22 / 33
25. Nested method calls
Method calls can also be nested, as the following example shows:
NSString *str =
[[NSString alloc] initWithString:@"Hello World"];
Here, you first call the alloc class method of the NSString class and then
call the initWithString: method of the returning result from the alloc
method, which is of type id, a generic C type that Objective-C uses for an
arbitrary object.
Note
In general, you should not nest more than three levels because anything
more than that makes the code difficult to read.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 23 / 33
26. Defining properties
Properties enable you to expose the fields in your class so that you
can control how values are set or returned.
In the earlier example we saw that we can directly access the fields of
a class using the ”->” operator.
However, this is not the ideal way; ideally, you should expose your
fields as properties in the interface.
// expose the rate field
-(float) rate; // get the value of rate
-(void) setRate:(float) value; // set the value of rate
// expose the name field
-(NSString *) name; // get the value of name
-(void) setName:(NSString *) value; //set the value of name
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 24 / 33
27. Getting and setting properties
To set the value of these properties, you need to call the methods prefixed
with the set keyword:
SomeClass *sc = [[SomeClass alloc] init];
[sc setRate:5.0f];
[sc setName:@"Wei-Meng Lee"];
To obtain the values of properties, you can either call the methods.
NSLog([sc name]); // call the method
To make a property read-only, simply remove the method prefixed with the
set keyword.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 25 / 33
28. Initializers
When you create an instance of a class, you often initialize it at the same
time.
SomeClass *sc = [[SomeClass alloc] init];
The alloc keyword allocates memory for the object; and when an object is
returned, the init method is called on the object to initialize the object.
The init method is defined in the NSObject class, which is the base class
of most classes in Objective-C.
Convention
If you want to create additional initializers, you can define methods that
begin with the init word (use of the init prefix is more of a norm than a
hard-and-fast rule).
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 26 / 33
29. Memory management
Like most other popular languages, Objective-C supports garbage
collection, which removes unused objects when they go out of scope
and hence releases memory that can be reused.
However, because of the severe overhead involved in garbage
collection, iOS does not support garbage collection.
This leaves the developer to manually allocate and de-allocate the
memory of objects when they are no longer needed.
Note
In the CSLP we are not targeting iOS, but still it seems worthwhile to
learn a little about reference counting. Recent versions of Mac OS X and
iOS include automatic reference counting, making memory management
the same on Mac OS X and iOS.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 27 / 33
30. Reference Counting
To help you allocate and de-allocate memory for objects, iOS uses a
scheme known as reference counting to keep track of objects to
determine whether they are still needed or can be disposed of.
Reference counting basically uses a counter for each object; and as
each object is created, the count increases by 1.
When an object is released, the count decreases by 1.
When the count reaches 0, the memory associated with the object is
reclaimed by the OS.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 28 / 33
31. Reference counting example
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 29 / 33
32. Reference counting example
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 29 / 33
33. Reference counting example
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 29 / 33
34. Reference counting example
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 29 / 33
35. Reference counting example
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 29 / 33
36. Reference counting example
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 29 / 33
37. alloc
The alloc keyword allocates memory for an object that you are creating.
An example is as follows:
NSString *str = [[NSString alloc] initWithString:@"Hello"];
Here, you are creating an NSString object and instantiating it with a
default string.
When the object is created, the reference count of that object is 1.
Because you are the one creating it, the object belongs to you, and it is
your responsibility to release the memory when you are done with it.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 30 / 33
38. new
Besides using the alloc keyword to allocate memory for an object, you can
also use the new keyword, like this:
NSString *str = [NSString new];
The new keyword is functionally equivalent to
NSString *str = [[NSString alloc] init];
As with the alloc keyword, using the new keyword makes you the owner of
the object, so you need to release it when you are done with it.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 31 / 33
39. retain
The retain keyword increases the reference count of an object by 1.
Consider the following example:
NSString *str = [[NSString alloc] initWithString:@"Hello"];
NSString *str2 = str;
Here, you do not own str2 because you do not use the alloc keyword on
the object. When str is released, the str2 pointer will no longer be valid.
To ensure that str2 is available even if str is released, you need to use the
retain keyword:
NSString *str = [[NSString alloc] initWithString:@"Hello"];
NSString *str2 = str;
[str2 retain]; // str2 now also "owns" the object
[str release]; // str can now be released safely
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 32 / 33
40. release
When you are done with an object, you need to manually release it by
using the release keyword:
NSString *str = [[NSString alloc] initWithString:@"Hello"];
//...do what you want with the object...
[str release];
When you use the release keyword on an object, it causes the reference
count of that object to decrease by 1.
When the reference count reaches 0, the memory used by the object is
released.
Stephen Gilmore (School of Informatics) Computer Science Large Practical Friday 12th October, 2012 33 / 33