Objective C Crash Course

in

Objective C is effectively the C programming language with things added to it to make it more Object Oriented.

Control statements like if, for, while, switch, operators & data types all come from the C programming language. You should be able to use any old C code (even from 20 years ago), put it into an Objective C compiler and have it work with little modification.

So we have this newer language (Objective C) built on an older language (C), so we need a way to indicate which parts of the code are for the Objective C language and which parts are for the C language.

Parts of Objective C code can be identified by:

  • Square brackets [class method/message]
  • The @ sign @autoreleasepool, @try, @catch, @property

Like many other languages, you have a main function which is executed when the program is run, this is the entry point into your application.


Arrays

In Objective C you have a few types of arrays. The regular C Style arrays (which are inherited from C) and mutable and immutable arrays. These are pretty straight forward, the examples below explain it a little better.

C Style Arrays

C style arrays can hold the same type only, they can be fixed or dynamic by omitting the number when initializing it.

// C Style Arrays
int multipleValues[5] = { 1, 2, 3, 4, 5 }; // Fixed
int multipleValues[] = { 1, 2, 3, 4, 5 };  // Dynamic

// Access with
multipleValues[3]; // 3rd element (0 based index)

// Note: C style arrays have no bounds checking,
int x = 99;

// accessing an area of unknown memory (returns eg: `1953674157`)
multipleValues[x];

Objective C Style Arrays

Objective C style arrays are more flexible, you have 2 types, mutable and immutable arrays.

// Objective C Style Arrays - Immutable
NSArray *myArray = [[NSArray alloc] initWithObjects: @"first", 10, [[NSDate alloc] init], nil];

// Shorthand
NSArray *myShortArray = @[@"item 1", 10, [[NSDate alloc] init]]; // no `nil` for shorthand

// Objective C Style Arrays - Mutable
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects: @"first",  10, [[NSDate alloc] init], nil];

// Adding or removing objects
[myArray addObject:@"fourth"];
[myArray removeObjectAtIndex: 1]; // Moves up all indexes in the array

Dictionary

You can use a dictionary to store key => value items. Unlike arrays dictionaries can have a key that is a string.

Dictionaries (like arrays) come in 2 flavours, mutable and immutable.

Immutable Dictionaries

NSDictionary *cities = [[NSDictionary alloc]
                        initWithObjectsAndKeys: // Notice, `Object` THEN `Key`
                            @"London", @"LN",
                            @"Cardiff", @"CA",
                            @"Brighton", @"BR",
                        nil];

NSString *someKey = @"LN";
NSLog(@"Value is: %@", [cities objectForKey: someKey]);

// Shorthand for creating immutable dictionaries (no `nil` required)
NSDictionary *shorthand = @{ @"key" : @"object", @"key2" : @"object2"};

Mutable Dictionaries

Like arrays there is also a Mutable version.

NSMutableDictionary *cities = [[NSMutableDictionary alloc]
                        initWithObjectsAndKeys:
                            @"London", @"LN",
                            @"Cardiff", @"CA",
                            @"Brighton", @"BR",
                        nil];

[cities setObject:@"Manchester" forKey:@"MN"];

NSString *someKey = @"MN";
NSLog(@"Value is: %@", [cities objectForKey: someKey]);

Fast Enumeration

Fast Enumeration is similar to the php foreach. While it seems this is another syntax shortcut, it actually uses a different method under the hood, and so is faster then doing an explicit for or while loop.

NSString *soundPath = @"/System/Library/Sounds";
NSFileManager *fileManager = [[NSFileManager alloc] init];

NSArray *soundFiles = [fileManager subpathsAtPath:soundPath];

for (NSString *file in soundFiles) {
    NSLog(@"File is: %@", file);
}

Creating Objects

Creating objects in Objective C is a 2-stage process. The first stage is allocation where we allocate the memory for this object, the second stage is the initialization, and this is where we construct our object ready for use.

// The first stage is allocation, Objective C will go out to an area of memory,
// and reserve some memory for this object, and return the "addressing memory"
NSDate *myDate = [NSDate alloc]; // Represents a `pointer` to an `NSDate` Object.

// Now we can use that pointer for the second stage of object creation
// Object Initialization - This can vary depending on class, get the object ready for use
myDate = [myDate init];

// We can do the above in one line using:
// NSDate `alloc` returns a pointer, which `init` can then execute upon
NSDate *myDate = [[NSDate alloc] init];

// Custom Initializers (passing through arguments)
NSDate *myDate = [[NSDate alloc] initWithTimeIntervalSince1970:2];
# Returns: `1970-01-01 00:00:02 +0000`

// Shorthand array syntax (for immutable arrays only)
NSArray *newArray = @[ @"apples", 10, [[NSDate alloc] init] ];

The methods alloc & init are inherited from the superclass NSObject, this is true of your own classes as well.


Objects and Pointers

There’s a key difference when creating simple primitive variables as to objects. In Objective C all objects are accessed using pointer types (the * asterisk when we’re declaring a variable).

If you create a variable that holds an Object (any object), that variable is now a pointer type.

int someInteger = 100; // 4 bytes
NSString *message = @"Hello Anil"; // 0x10011be60 - A pointer to the location in memory

someInteger now actually holds that variable directly, in this case it holds 4 bytes.

When you create an object variable, the variable itself does not hold the contents of the object (in this case ‘hello’), instead it holds an address (aka a reference or pointer) to a location in memory where the object actually exists.

You’ll never need to know the actual address of the pointer, but it’s important to understand what’s happening behind the scenes.



Automatic reference counting (ARC)

Before iOS 5, creating objects also required you to release that object when your finished with it. ARC (Automatic reference counting) was added in iOS 5; it’s all about simplifying memory management.

NSDate *myDate = [[NSDate alloc] init]; // Before iOS 5, Create your object as usual
// do stuff... e.g. [myDate someMethod];
[myDate release] // Release that object to reclaim the memory

The issues with conventional memory management is that if a class was allocated and initialized, a method used, and then we release that object, you have something called a dangling pointer. If you try to use that same object again, it will fail. If you create an object and release to late - or you don’t release at all, you will have a memory leak. With large apps, this becomes very difficult to manage.

With ARC, this headache disappears, you no longer have to write retain or release calls any more, you don’t even have to think about it. You simply create your object, use it and ARC will handle the clean-up. Bare in mind retain and release has not disappeared from Objective C, Objective C still uses reference counting, but it is now within the compiler process.

The compiler (LLVM) scans your code, and synthesizes these retain & release in the build process at the best point in the program. Effectively, the compiler is writing the same code you would (if you was really good at writing memory management code). You don’t actually see these lines - ARC adds them silently during the compilation process.

With ARC turned on, Xcode won’t even allow you to call a release method on an object.


+/- Signs before method signatures

Reading documentation or looking at code, you will see + or - signs to the left of the signature. If your coming from Java (or any other language), you’ll probably think these mean public or private, they don’t.

- Minus sign (Instance Methods)

The minus - sign is common with most classes. These are known as instance methods. You’ll call these methods on an instance of an object that you’ve already created.

NSDate *today = [NSDate date]; // Creating a new `instance`

// Call the `- dateByAddingTimeInterval` (instance method) of `today`
[today dateByAddingTimeInterval:2];

+ Plus sign (Class Methods)

The plus + sign is a class method; you would call these methods using the class name.

// Calling the `+ date` method os the `NSDate` class
NSDate *today = [NSDate date];

Creating Custom Classes

In Objective C, like other C languages, you define your classes in 2 files. The interface (.h) and the implementation (.m).

Interface

The interface simply defines the method signatures, but not the method body. So it tells us what’s available in this class for us to use (similar to interfaces from other languages).

Implementation

The implementation is where the magic happens, this is where we write all our code (which must conform to the signature defined in the interface).

Example of Interface and Implementation

// Player.h
#import <Foundation/Foundation.h>
@interface Player : NSObject
-(void)simpleMethod;
@end

// Player.m
#import "Player.h"
@implementation Player
-(void)simpleMethod {
    NSLog(@"Implementation in `Player` Class from `simpleMethod`!");
}
@end

// main.m
#import <Foundation/Foundation.h> // System classes use < >
#import "Player.h" // Own classes use quotes " "

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSLog(@"Hello World from `main.m`");
        Player *anil = [[Player alloc] init];
        [anil simpleMethod];
    }
    return 0;
}
# Console Output
# Hello World from `main.m`
# Implementation in `Player` Class from `simpleMethod`!

So basically, we have our implementation and interface, in the main method, we import our custom class using import, we use quotes for custom classes, and <> for system classes. We then create a new instance of Player into anil and init it. As described above, the alloc and init methods we use to create our object are inherited from the NSObject superclass we extend in Player.h.


Creating Properties

In previous years of Objective C the way we would create properties on our objects would be by defining instance variables (ivars), these are variable definitions wrapped inside a pair of braces {} inside the interface but outside the method declaration.

// Player.h - `instance variables` example
@interface Player : NSObject {
    int age;
    NSString *name;
}
-(void)simpleMethod;
@end

The downside to this is that these properties are not accessible from outside the class, so you’d have to write accessor methods for them (setters and getters) manually (for each variable!). This is quite tedious, luckily there’s a better way.

Hello @property

We can use the @property syntax to synthesize (or generate) our getter and setter methods for us to allow access to these ivars outside the class. So how do we use the @property syntax to synthesize our accessors?

// Player.h
#import <Foundation/Foundation.h>
@interface Player : NSObject  // { int age; NSString *name; } // Not required!
    @property int age; // Add the property, we `@synthesize` in the implementation
    @property (nonatomic, strong) NSString *name; // another property
    -(void)simpleMethod;
@end

// Player.m
#import "Player.h"
@implementation Player
    @synthesize age, name; // Generates the accessor methods
    -(void)simpleMethod {
        NSLog(@"Implementation from `simpleMethod`!");
    }
@end

// main.m - Example usage of our getters and setters
Player *anil = [[Player alloc] init];
[anil setAge:20]; // Setter (Our `synthesized` methods)
[anil age:20];    // Getter (name of variable (no `set` prefix))

Although the above is a basic example, we are also required to specify whether the property should be thread safe, and whether or not to hold a strong reference to the property.

@property (nonatomic, strong) NSString *name;

nonatomic means that we’re not worried about multiple threads trying to access this object at the same time. So Objective C does not generate thread safe code for our getters and setters. By default (if not specified) the @property is defined as atomic, so it WILL generate thread safe code. nonatomic is a little faster and its more common to see in iOS.

strong comes along with Automatic Reference Counting, what strong does is tell the compiler that we want our class (in this case Player) to hold a strong reference to this property (name). So the Player class owns the property name. As long as a Player object exists, the NSString object inside it that holds the name of the Player object should also exist. Before ARC it was common to see the word retain instead of strong.

Objective C 2.0 dot syntax

Objective C 2.0 adds a great feature to the language, the dot syntax. In other languages this is a very common way to get and set property values.

anil.age = 20; // Setter
anil.age; // Getter

// Instead of
[anil setAge:20]; // Setter (Our `synthesized` methods)
[anil age:20];    // Getter (name of variable (no `set` prefix))

Although this is a great helper, you’ll probably not use this often, note that dot syntax only works for synthesized properties and only properties (not methods), so although this is a great feature, probably best stick to [] square bracket syntax until you’re less of a noob.