iOS Pain Points: Multiselect of UITableViewCell children in Interface Builder

This is a quick one.

Multiselect in a UI designer is a pretty standard operation. If I want to change a property on a number of controls at once, I should be able to simply ctrl-click them (or command-click, or option-click, and so on) to select them all, and change the property.

Unfortunately Interface Builder doesn’t seem to support multiple selection on controls in different UITableViewCells. Attempting to do so always results in the first control being deselected.

However, there is a workaround, which is why this entry is really half ‘iOS Pain Points’, and half ‘iOS Quick Tips’. It turns out you can multiselect across table cels by command-clicking in the Document Outline window on the left.

Not entirely intuitive, but it does the trick!

iOS Pain Points: Constants and enums are not discoverable

Let’s say I want to use a UIImagePickerController to take some photos.

UIImagePickerController* controller = [[UIImagePickerController alloc] init];
controller.sourceType = 

Ok, I’ve finished typing the = sign on the second line. Now I would like to type the actual source type value that I am assigning. Surely Xcode can help me out with this? I mean, intellisense/content assist/code completion is a pretty basic IDE feature. But Xcode does nothing by default. Ok, fine. I’ll hit Esc to manually invoke autocompletion.

Xcode, in all its wisdom, gives me a completely useless list of dozens or hundreds of irrelevant entries.

Fine, I happen to know that enums generally start with the name of the control. I will manually type in ‘uiimagepickercontrollers’, to finally get a list of the available UIImagePickerControllerSourceTypes. All in all, it’s a horrible user experience.

Now let’s move on to something even worse. It’s time to configure my controller’s media types:

controller.mediaTypes = wtf?

Ok, so mediaTypes is an array of, well, stuff, since Objective-C arrays aren’t strongly typed, as we saw in the previous ‘iOS Pain Points’ entry. So I have no information on how to use this API, and code completion is telling me nothing. No problem, I’ll just look at the Quick Help window in Xcode.

Great, it’s ‘An array’. Thanks, Xcode. Not to worry, though. I’m familiar with the standard mentioned above, where types generally start with the name of their control, so I’ll just look for UIImagePickerControllerMedi… ok, scratch that. Turns out, I actually need to use a constant such as kUTTypeImage, which is declared in a different file. Or to put it another way, it’s literally impossible to use the UIImagePickerController without looking at the documentation to figure out what the allowed values are for what fields. It’s a case study in poor, non-discoverable API design and inadequate IDE integration.

For reference, here’s what using an enum in C# / Visual Studio looks like:

Apple could learn a thing or two from Microsoft here.

iOS Pain Points – No strongly-typed collections

This is the first entry in the iOS Pain Points series. This series will detail some of the downsides and pitfalls of iOS development, and will include various aspects of Objective-C, Cocoa, and XCode.

Today’s iOS Pain Point is the lack of strongly typed or generic collections. .NET developers eat, sleep, and breathe generic collections, and this is something I found lacking when working with iOS.

Purists may¬†argue that due to Objective-C’s dynamic nature, there is no need for strong typing, but the reality is that it can prevent bugs. Consider the following code:

NSArray* names = [[NSArray alloc] initWithObjects:
                      @"Bob", @"Fred", @"James", "@Mike", @"Kyle", @"Steve", Nil];

It compiles, but crashes when you run it. And this is not a contrived example; it’s a bug I ran in to while first starting with Objective-C. Granted, improved syntax coloring in XCode could make this bug immediately obvious, but it’s still a bug that never should’ve existed.

If that’s too easy and obvious for you, consider this code snippet:

-(void) FireBullet
{  
    Bullet* bullet = [[Bullet alloc] init];
    bullet.position = [self calculateBulletPosition];
    [bullets addObject:bullets];
}

-(void) Update
{
    for(Bullet* bullet in bullets)
    {
        [bullet updatePosition];
    }
}

This compiles fine too, but again, it crashes with an ‘Unrecognized selector’. And although it’s a trivial error that is easy to fix, it is, as before, an error that never should’ve existed in the first place.