(My) common mistakes learning Objective C and iPhone programming

In this post I would like to gathering all the mistakes I did in the past months while I was learning Objective C, and although I’m still a learner and I will face new obstacles soon, I hope to keep in mind some concepts and language features better, by talking about those and help new students save time on google and extra headache.
So, let’s start with the errors list:

1. No “foo” method found / “foo” may not respond to selector

I was implementing a method (inside .m file) not defined before in the header (.h)

2. Bad positioning and behavior of UITabBarController’s view

I added the UITabBarController’s view to a subview rather than the main window (the only place where you can add it)

3. Create my own null wrapper

Objective C doesn’t allow nil values to be added to collections (NSArray, NSDictionary and so on) but just objects, so I got the smart idea of realize a dummy class representing null values. In this way I can create instances of “MyDummyNullObject” and add them to any kind of collection. However I successively discovered that Cocoa was already providing such class: NSNull! Moreover it offers a better implementation, because it’s a singleton, thus you don’t have to create more than one object but just relay on it’s “factory method”: [NSNull null] which will return the shared NSNull instance.

4. Write repeated @synthetize statemens

There is no need to write “@synthetize” for each class property, we can simple write it once followed by a comma delimited list of properties (ie: @synthetize prop1, prop2, prop3, prop3, prop4;)

5. Create unnecessary pointers for scalar types

Scalar types are basically all that is not a class (NSInteger, NSUInteger, BOOL…), for these types the asterisk is not required! (basically asterisk means: “I’m gonna to create a pointer to an instance of a class”)

6. Try to compare strings and other objects by using == operator

by using == we are not comparing strings values but pointers (which will be always different despite their content). The right way is using isEqualToString:, isEqual: or compare: (and its variants)

7. Check sqlite’s database modifications in the wrong place

I spent a lot of time to figure out why my insert and update commands did not modify database content, then I realized that I was looking at the wrong file! Project’s resources are copied during the build phase, and you can find them under:
“/Users/$user_name/Library/Application Support/iPhone Simulator/$sdk_version/Applications/$app_id/$app_name.app” (of course you have to replace $foo with your personal info)

8. Initialize variables inside switch/case statement

Is not possible to initialize a variable as first declaration inside a case, if you try to compile the following code:

switch (value) {
    case 5:
        NSNumber *number = [[NSNumber alloc] initWithInt:value];
        NSLog(@"my number: %i", [number intValue]);
        break;
    default:
        break;
}

The compiler will rise an “Expected expression before NSNumber”. To avoid errors we can simply declare the instance variable before the switch statement in this way:

NSNumber *number;

switch (value) {
    case 5:
        number = [[NSNumber alloc] initWithInt:value];
        NSLog(@"my number: %i", [number intValue]);
        break;
    default:
        break;
}

or cheat the compiler by writing a command like an NSLog, before the assignment:

switch (value) {
    case 5:
        NSLog(@"go on without errors!");
        NSNumber *number = [[NSNumber alloc] initWithInt:value];
        NSLog(@"my number: %i", [number intValue]);
        break;
    default:
        break;
}

of course this last example is really nonsense, but it gives you the idea :)

UPDATE:
As suggested by Dmitry Chestnykh in the comments, there is a better and easy approach to avoid such errors (pay attention to the curly braces in the case):

switch (value) {
    case 5: {
        NSNumber *number = [[NSNumber alloc] initWithInt:value];
        NSLog(@"my number: %i", [number intValue]);
        break;
    }
    default:
        break;
}

9. Unrecognized selector sent to instance

I was declaring a pointer of type NSMutableArray and assigning it to an NSArray (a simple typo error), in this way:

NSMutableArray *array = [[NSArray alloc] init];

then I was filling it with “addObject”:

[array addObject:myObject];

and at runtime I got the “unrecognized selector sent to instance”, this because I allocated an NSArray which doesn’t have “addObject” among its methods (in fact an NSArray is immutable and objects contained in this collection are specified during its creation)… anyway I don’t understand why the compiler does not rise an error at compile time :^/

10. UITableViewCells mixed up after scrolling UITableView

One of the most complex ui element to understand in the UiKit framework is undoubtedly UITableView, because it’s composed by different elements (like UITableViewCell) and requires a good knowledge of how it has been conceived in order to make it work the right way and with good performance. The main key concept behind this cool component resides in the method “tableView:cellForRowAtIndexPath“. The scope of this one is to return the UITableViewCell for a specific NSIndexPath and is called automatically at runtime. For performance reasons, it should returns cached objects by using dequeueReusableCellWithIdentifier and only if there is no a cached version (the method returns nil), initialize the required cell (that is allocating a UITableViewCell instance and configuring its views). In case of cached cells, you must avoid adding/removing views from the cell and limit changes to colors, label’s values and similar. Any other “invasive” change can results in strange table behavior and performance decrease.