Notes

"Gotchas" in XCode and Objective-C

  1. NSLog()
  2. Sending a message to nil
  3. Not hooking up your IBOutlets in Interface Builder
  4. Not using the pointer * operator when you should
  5. Using the pointer * operator when you should not
  6. Not balancing your square brackets when calling methods
  7. Incorrectly declaring properties
  8. Neglecting to #include a .h file you need
  9. Neglecting to add a Framework to your project
  10. Causing memory leaks by not properly releasing your objects
  11. Messaging a deallocated object


1) Common issues when using NSLog()

A) Omitting the @ in front of a NSString literal

The wrong way:

For example, the following code:

NSLog("Hello from console!");

produces these warnings when the project is built:

warning: passing argument 1 of 'NSLog' from incompatible pointer type
warning: format not a string literal and no format arguments

and then crashes with nothing printed to the console when the project is run.

The right way:

The correct way to write the statement is:

NSLog(@"Hello from console!");

Notes: NSLog expects NSStrings to print. Remember that a C-string like "Hi there!" is simple array of characters (the char type)

An NSString looks like @"Hi there" and is a class with methods and properties, and is what we use 99% of the time when programming on iPhone

B) Using the wrong string format specifier in your NSString

The wrong way:

For example, the following code:

int age = 25;
NSLog("I am %@ years old",age);

produces no warnings when the project is built:

No warning, so life is good, right?

and then crashes with nothing printed to the console when the project is run.

The right way:

The correct way to print out an int value is to use the %d format specifier:

int age = 25;
NSLog("I am %d years old",age);



While we're here, the correct way to print out a float value is to use %f as a format specifier:

float age = 25.0;
NSLog("I am %f years old",age);



And the correct way to print out a NSString value (or any other subclass of NSObject) is to use %@ as a format specifier:

NSString *age = @"25.0";
NSLog("I am %@ years old",age);

Notes: The complete list of string format specifiers is at: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/Strings/Articles/formatSpecifiers.html


2) Sending a message to nil

Sending a message to an object with a value of nil is a no-op (nothing happens)

The wrong way:

For example, the following code:

// myMutableArray is an ivar (instance variable)
[myMutableArray addObject:@"Moe"];
NSLog(@"myMutableArray = %@",myMutableArray);

produces the following output when the code is run because myMutableArray was never initialized. Note that there are no errors or warnings when the code is run.

myMutableArray = (null)



The right way:

The correct way to write the statement is to make sure that the ivar has been initialized :

// myMutableArray is an ivar (instance variable)
myMutableArray = [[NSMutableArray alloc] init]; // initialize the ivar
[myMutableArray addObject:@"Moe"];
NSLog(@"myMutableArray = %@",myMutableArray);

Notes: This is a very common error.


3) Not hooking up your IBOutlets in Interface Builder

Neglecting to hook up your outlets and actions in IB leads to messages being send to nil ivars, again resulting in no-op behavior.


4) Not using the pointer * operator when you should

Any variable that points at a subclass of NSObject needs the * operator in front of it.

The wrong way:

For example, the following code:

NSMutableArray myMutableArray; // * incorrectly omitted
myMutableArray = [[NSMutableArray alloc] init];

produces the following warnings and errors when the code is built:

error: statically allocated instance of Objective-C class 'NSMutableArray'
error: statically allocated instance of Objective-C class 'NSMutableArray'
error: incompatible types in assignment



The right way:

The correct way to write the statement is to use the pointer * operator :

NSMutableArray *myMutableArray; // use the pointer * operator
myMutableArray = [[NSMutableArray alloc] init];

Notes: There is one important exception to this. When using the id type, the * is generally not used because id is actually void * behind the scenes. The following would be the correct way to write the code with the id type:

id myMutableArray; // don't use the pointer * operator
myMutableArray = [[NSMutableArray alloc] init];


5) Using the pointer * operator when you should not

Using a pointer operator in front of a basic C-type like int turns it into a pointer to a memory address, which might not be what you want to do.

The wrong way:

For example, the following code:

int *num1 = 5;
int *num2 = 10;
int *sum = num1 + num2;

produces the following warnings and errors when the code is built:

warning: initialization makes pointer from integer without a cast warning: initialization makes pointer from integer without a cast error: invalid operands to binary + (have 'int *' and 'int *')



The right way:

int, float, double etc... usually don't need the pointer * operator.

int num1 = 5;
int num2 = 10;
int sum = num1 + num2;