Effective Objective-C

Knowing how to write Objective-C code is far from a perfect software engineer, it is also of significance to take a deeper look at how it works and why it works. Recently I am reading the Book Effective Objective-C 2.0, which has inspired me a lot. So I decided to write this blog to summerize what I have learnt.

1. Objective-C

Objective-C differs from other object-oriented languages such as C++ or Java in that it uses a messaging structure rather than function calling.

// Messaging (Objective-C)
Object *obj = [Object new];
[obj performWith:parameter1 and:parameter2];
// Function calling (C++)
Object *obj = new Object;
obj->perform(parameter1, parameter2);
  • Messaging structure: The runtime decides which code gets executed.
  • Function calling: The compiler decides which code will be executed.

When you declare a variable that is to hold a reference to an object, the syntax looks like this:

NSString *someString = @"The string";

All Objective-C objects must be declared in this way because the memory for objects is always allocated in heap space and never on the stack. It is illegal to declare a stack-allocated Objective-C object:

NSString stackString;
// error: interface type cannot be statically allocated

To summerize this concept, Objective-C uses a messaging structure with dynamic binding, meaning that the type of an object is discovered at runtime. The runtime, rather than the compiler, works out what code to run for a given message.

2. Minimize Importing Headers in Headers

  • When writing an import into a header file, if the import can be forward declared, prefer that. Doing so avoids coupling classes together as much as possible.
  • Sometimes, forward declaration is not possible, as when declaring protocol conformance. In such cases, consider moving the protocol-conformance declaration to the class-continuation category, if possible. Otherwise, import a header that defines only the protocol.

3. Prefer Literal Syntax over the Equivalent Methods

  • Use the literal syntax to create strings, numbers, arrays, and dictionaries. It is clearer and more succinct than creating them using the normal object-creation methods.
  • Access indexes of an array or keys in a dictionary through the subscripting methods.
  • Attempting to insert nil into an array or dictionary with literal syntax will cause an exception to be thrown. Therefore, always ensure that such values cannot be nil.