It’s been a while since I completed my first iPhone development project, and I figured I’d finally write up my initial experience with this platform. A bit late, but better than never…
To put this into perspective, here’s a brief summary of my previous professional programming background:
I worked with C++ back in University but quickly adopted Java in 1998 and never looked back (good riddance to pointers and manual memory management!). Java served me well for the better part of the past 10 years, but I’ve increasingly become a fan of dynamic languages, and Ruby in particular (although I’ve dabbled a bit with Python as well). These days I mainly work with Ruby (mostly Ruby on Rails, but also standalone apps such as daemons, command line apps, etc.). Among many other reasons, I just love its expressiveness over Java’s verbosity.
With this in mind, I was admittedly a bit hesitant at first about iPhone development using Objective-C, even though I was definitely curious about the CocoaTouch platform (and Cocoa in general).
At first glance, Objective-C syntax looks quite odd. Instead of the dot-notation for method calls that Java and Ruby use (e.g.
"foobar".length), Objective-C uses a square bracket based message passing syntax (e.g.
[@"foobar" length]). This is harmless enough for simple method calls, but can become confusing when using nested calls (e.g.
[[[MyClass alloc] init] autorelease]). Apparently, Apple decided this was the case as well, so when they introduced their simplified support for properties in Objective-C 2.0, they chose to go with dot-notation. This definitely cuts down on some of the clutter (especially when setting properties), but it also leads to a slightly awkward, inhomogeneous mix of notations in the code, as dot-notation cannot be used for regular method calls (and in fact some long-time Objective-C developers are boycotting the new properties syntax for that very reason). But in the end, this is a relatively minor stylistic difference, and I eventually got used to it.
The other Objective-C oddity is the Smalltalk-inspired way that parameters are passed to methods. Most current programming languages pass parameters as comma-separated lists. Objective-C essentially breaks method names up into multiple segments, each of which has its own parameter. This means that you end up with method signatures like this:
Invoking this method would look like this:
It felt weird at first, but once I got my head wrapped around this syntax, I actually kind of started to like it, as it makes method calls read like regular English sentences. I have however found that it can be difficult to come up with natural sounding method and parameter names for my own classes, so my preference would be a C-based method call syntax with named params like Python has. But in the end, I got used to this syntax fairly quickly.
Probably the thing that bothers me most about Objective-C / Cocoa is the overall verbosity, especially compared to a very succinct language like Ruby. This is partially because variables need to be declared, partially because Cocoa’s method names tend to be long, and of course because as a C-derived language, Objective-C simply isn’t as expressive as a language like Ruby, with its blocks, enumerations, literal syntax for creating arrays and hashes, etc.
Then there’s the usual duplication also found in C/C++ with its header and implementation files. For example, in Ruby I can define a property simply by using
attr_accessor :foo. In Objectice-C, I need to explicitly declare the actual member variable as well as the property in the header file, and add a synthesize statement to the implementation file. And this is already the shorthand syntax for properties…
Perhaps the thing I was most worried about: Memory Management. Objective-C 2.0 actually introduced garbage collection, but unfortunately this isn’t supported on the iPhone. Luckily, as it turns out, Objective-C’s retain count based memory management combined with autorelease pools is actually quite elegant and a major improvement over C/C++. I won’t go into details here (there are many resources on this topic), but the bottom line is that as long as you adhere to the accepted conventions (particularly regarding which methods return autoreleased vs. non-autoreleased objects), you should be fine. With Instruments, Apple also provides a powerful tool to help track down actual memory leaks. Would I prefer garbage collection? Absolutely! But the situation isn’t as bad as I had feared.
Objective-C also provides many nice features, such as Protocols and Categories. Protocols are very similar to Java Interfaces and are heavily used for delegation (see below). Categories allow functionality to be added to existing classes. For example, you could use this mechanism to allow NSDictionary, NSArray, or other NSObject subclasses to generate a JSON representation. They remind me of a less powerful (but still convenient) version of Ruby Mixins (less powerful because Mixins allow modules to be mixed into arbitrary classes, whereas Categories are implemented for a specific class).
This is really the best part of iPhone development. Having mostly worked on server side code, I’ve never been much of a GUI developer. But with a few positive exceptions (such as Qt), most of the GUI frameworks I have messed with were quite painful (MFC anyone?), with horrendous amounts of unmaintainable, auto-generated code.
CocoaTouch (like its big brother Cocoa on the Mac) is very well thought out and makes good use of design patterns. In particular, it heavily relies on delegation rather than inheritance, which leads to significantly cleaner and more modular code. For example, instead of subclassing a UI control in order to add the desired custom behavior, you typically implement the behavior in your controller class and specify this as the delegate for the UI control.
Aside from a few lines of boilerplate code that are part of the project templates, there is absolutely no auto-generated code. This is mostly possible because Interface Builder stores actual, serialized object instances inside xib files and all custom behavior is injected using the delegate mechanism.
CocoaTouch also provides very simple, high-level APIs for many powerful features, such as the iPhone’s camera / image picker.
The only thing that bugs me a lot is the disconnect between the Objective-C based high-level Cocoa API and the C-based lower-level APIs. Often times, the high-level APIs are limited to a few common cases, but when you need to stray from these, you need to talk straight to the underlying low-level APIs. This leads to an awkward mix of nice, object-oriented Objective-C code and ugly, procedural C code.
The various development tools are an integral part of the iPhone SDK. In particular, Xcode is a very decent IDE. It may not be the best IDE I’ve ever used, but it gets the job done and even sports some modern IDE features (such as refactoring). I wish it had Git support, though.
Interface Builder is an extremely convenient tool, so I try to use it whenever it makes sense. However, I do have a few complaints: Many properties are not exposed in IB, so they have to be set manually in the code. More importantly, IB is not extensible at all. For example, I would like to be able to implement my own subclass of UIView and have its relevant properties show up in IB. If my UIView subclass defines a text property (perhaps with some sort of annotation that specifies additional, Interface Builder specific metadata), I would like to see a text field in IB. If I define a color property, I would like to see a color picker, etc. Hopefully this will be possible in a future version.
Instruments is a powerful tool for finding memory leaks and performance bottlenecks. I have only used this a little bit, but it’s good to know that it’s there when I need it.
My major complaint in this area is about the horribly complicated and error prone provisioning process. But I’ll save this rant for another blog post.
Overall, iPhone development is a lot of fun, and a very refreshing change from web development. The iPhone is an amazingly powerful device, and after the initial learning curve, it is surprisingly easy to leverage many of its unique abilities, such as the accelerometer, multi-touch, Internet connection, and more.
Now that I got this post out of the way, I plan on posting more about specific iPhone development topics. Stay tuned!