views:

167

answers:

4

Say I want to create an instance of NSString, which is initialized to a certain value depending on the value of another variable. Normally, I would do

NSString *string;
if(foo == 1)
    string = @"Foo is one.";
else
    string = @"Foo is not one.";

However, in some sample code that I've seen, I've seen people do

NSString *string = nil;
if(foo == 1)
    string = @"Foo is one.";
else
    string = @"Foo is not one.";

What is the difference between these two, and which method is preferred?

+4  A: 

My personal preference is to initialize any variable immediately. However, in the sample you provided, these two methods are equivalent.

In C languages (i.e. C, C++, Obj-C) variables that are not initialized immediately may contain random garbage values. Using the the variable before it is initialized lead to unexpected behavior (ranging from hopefully crashing to getting unexpected behavior).

Example Consider the following example:

int abs;
if (argument > 0) abs = argument;
else if (argument < 0) abs = -1 * argument;
NSLog(@"%i", abs);

Here the code leaves abs variable uninitialized if argument is 0. So you would getting random values logged and then lead to corrupting the values in the rest of the program; and it would be hard to detect where the problem is!

If you use an uninitialized reference, you would most likely get a EXEC_BAD_ACCESS.

notnoop
+1  A: 

Setting variables to a value or to nil can make an uninitialized-value error easier to spot at run-time.

NSString *string = @"Foo is not one";
if(foo == 1)
    string = @"Foo is one.";

Various compilers are better at spotting uninitialized values these days.

One Objective C reason to set pointers to nil (after last usage) is garbage collection.

Stephen Hoffman
A: 

Generally you would probably set a variable to nil to make sure you start out with a known value state of the variable. So you know that the variable is nil starting out and then later on you can compare the variable against nil. A good example of this is Error checking with NSError like so

NSError *error = nil;
[SomeCocoaClass performOperationWithObject:obj error:&error];
if(nil != error){
//handle error
}

It's possible to create a variable and start out with an uninitialized state and then when you try to read that variable in later you get garbage and crash. It's just a good coding practice to initialize your variables to a known initial state then check against that state later on.

Colin Wheeler
+2  A: 

The assignment to nil is there so that no one ever looks at the code and worries that the variable is ever in an undefined state.

NSString *string;
NSLog(@"%p", string);

That code will print a garbage value since string's value is undefined.

Rather than write code like in your example, I prefer to use the ternary operator. Here's an example:

NSString *string = (foo == 1) ? @"Foo is one." : @"Foo is not one.";

Now string's value is always defined. If the expressions get complicated, and the line gets long, just use intermediate variables.

The best solution to many problems is to just eliminate the problem. This does just that.

Jon Hess