Notes
"Gotchas" in XCode and Objective-C
NSLog()
- Sending a message to
nil
- Not hooking up your
IBOutlets
in Interface Builder - Not using the pointer
*
operator when you should - Using the pointer
*
operator when you should not - Not balancing your square brackets when calling methods
- Incorrectly declaring properties
- Neglecting to
#include
a.h
file you need - Neglecting to add a Framework to your project
- Causing memory leaks by not properly releasing your objects
- 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!");
warning: passing argument 1 of 'NSLog' from incompatible pointer type
warning: format not a string literal and no format arguments
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
The wrong way:
int age = 25;
NSLog("I am %@ years old",age);
No warning, so life is good, right?
The right way:
The correct way to print out anint
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);
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];
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];
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;
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;