Archive for the ‘Mobile’ Category

A Useful UITableView Cell Creation Pattern

Saturday, December 19th, 2009

Like many iPhone apps, the app I’m currently working on uses several table views. Most of these display actual lists of data, and some are used as a convenient layout mechanism for input fields, navigation, and other UI elements (similar to iPhone preference screens).

UITableView and its associated classes like UITableViewCell, UITableViewDataSource, and UITableViewDelegate are very powerful, but they also require a fair amount of boilerplate code split across several methods. The specific matter that I am tackling in this post is the creation of cells, which happens inside the [UITableViewDataSource tableView:cellForRowAtIndexPath:] method. When dealing with only a single type of cell, it typically looks like this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // See if there's an existing cell we can reuse
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Foobar"];
    if (cell == nil) {
        // No cell to reuse => create a new one
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Foobar"] autorelease];
 
        // Initialize cell
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
        cell.textLabel.textColor = [UIColor blueColor];
        // TODO: Any other initialization that applies to all cells of this type.
        //       (Possibly create and add subviews, assign tags, etc.)
    }
 
    // Customize cell
    cell.textLabel.text = [NSString stringWithFormat:@"Row: %d", indexPath.row];
    // TODO: Any other customization
    //       (Possibly look up subviews by tag and populate based on indexPath.)
 
    return cell;
}

As you can see, there’s a lot of boilerplate code here. This works well enough with one type of cell, but if you’re dealing with multiple types of cells (particularly in a grouped table view), this approach quickly gets out of hand. You end up with a long method with large, ugly switch statements. But if you look at this method closely, you’ll notice that there are only a few cell-specific areas:

  1. The cell identifier (MyCell in my example). This is used to look up and reuse existing cells (e.g. when scrolling through a large table of items) and avoids the costly creation of new cells every time. It’s a standard cell creation pattern for the iPhone and makes a lot of sense, but it also means that the cell specific code is spread across several places.

  2. The initialization code. This is where a cell of a given type is initialized for the first time. If you can get away with the standard cell styles (which cover a few different layouts of labels and images), you usually don’t need to do much here, besides setting your colors, fonts, and perhaps selection style. Otherwise, this is where you want to create and add your subviews, and assign a tag to them so you can populate them later.

  3. The customization code. Given a cell with the correct properties and subviews (which may have been reused or created during this call), this is where you populate it with the correct data. This typically involves looking up some sort of data based on the indexPath, and setting it either on the cell itself (using the textLabel, detailTextLabel, or imageView properties) or on its subview. The latter requires looking up the subviews using the tags you’ve assigned earlier.

With this in mind, I decided to factor out all the cell specific code, resulting in a generic method in my base view that can be used to create all the cells of my app. Here’s what that method looks like:

- (UITableViewCell *)createCellForIdentifier:(NSString *)identifier
                                   tableView:(UITableView *)tableView
                                   indexPath:(NSIndexPath *)indexPath
                                       style:(UITableViewCellStyle)style
                                  selectable:(BOOL)selectable {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:identifier] autorelease];
        cell.selectionStyle = selectable ? UITableViewCellSelectionStyleBlue : UITableViewCellSelectionStyleNone;
 
        SEL initCellSelector = NSSelectorFromString([NSString stringWithFormat:@"initCellFor%@:indexPath:", identifier]);
        if ([self respondsToSelector:initCellSelector]) {
            [self performSelector:initCellSelector withObject:cell withObject:indexPath];
        }
    }
 
    SEL customizeCellSelector = NSSelectorFromString([NSString stringWithFormat:@"customizeCellFor%@:indexPath:", identifier]);
    if ([self respondsToSelector:customizeCellSelector]) {
        [self performSelector:customizeCellSelector withObject:cell withObject:indexPath];
    }
    return cell;
}

Structurally, this method is very similar to the previous one. It first tries to reuse an existing cell, creating and initializing a new one if it doesn’t find one. It then customizes the cell. You’ll notice that I’m using some performSelector calls here, coupled with a naming convention. For example, given an identifier of "Foobar", I will look for initCellForFoobar:indexPath and customizeCellForFoobar:indexPath to initialize and customize this cell respectively. A simple example might look like this:

- (void)initCellForFoobar:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath {
    cell.textLabel.textAlignment = UITextAlignmentCenter;
    cell.textLabel.textColor = [UIColor blueColor];
    cell.textLabel.font = [UIFont boldSystemFontOfSize:16.0];
}
 
- (void)customizeCellForFoobar:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath {
    cell.textLabel.text = [NSString stringWithFormat:@"Row: %d", indexPath.row];
}

Note that both methods are optional. In some cases (particularly in table views that are used for preferences or similar types of UI elements), there’s only a single cell of any given type, so I perform the complete initialization in initCellForFoobar and omit the customizeCellForFoobar method. In other cases, I may not require any special initialization and only have a customizeCellForFoobar method.

Obviously, the example above is trivial, and both methods can get significantly longer when dealing with custom subviews. In that case I am using the same tag based approach I mentioned above: Assign a tag to each subview inside initCellForFoobar, then look up the subview using the tag in customizeCellForFoobar. But the important thing is that the code is well factored, and the cell specific code is not mixed with boilerplate code.

Last not least, an example of the actual UITableViewDataSource method to create a new cell:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *identifier;
    BOOL selectable = YES;
    UITableViewCellStyle style = UITableViewCellStyleDefault;
 
    switch (indexPath.section) {
        case 0:
            identifier = @"Foo";
            break;
        case 1:
            identifier = @"Bar";
            selectable = NO;
            break;
    }
 
    return [self createCellForIdentifier:identifier
                               tableView:tableView
                               indexPath:indexPath
                                   style:style
                              selectable:selectable];
}

The example above is what I would typically use for a grouped table view, where each section contains a specific type of cell. But obviously this approach supports any type of table view, grouped or non-grouped. You just need to plug in your own logic to determine the type of cell, and leave everything else to the createCellForIdentifier:tableView:indexPath:style:selectable method we created earlier.

There are probably other approaches for simplifying working with table views, but this approach has worked very well for me. It really cuts down significantly on the amount of boilerplate code and allows me to focus on the actual application specific code.

Any questions, suggestions for further improving this, or perhaps alternative solutions that you’ve used? Leave a comment!

iPhone Development is Fun!

Sunday, May 10th, 2009

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).

Objective-C

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:

- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;

Invoking this method would look like this:

[myView insertSubview:mySubview atIndex:3];

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).

CocoaTouch

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.

Development Tools

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.

Conclusion

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.

I would love to be able to use CocoaTouch in conjunction with Ruby (such as RubyCocoa or MacRuby. But given that this is not an option on the iPhone, Objective-C is a decent alternative.

Now that I got this post out of the way, I plan on posting more about specific iPhone development topics. Stay tuned!

Evernote: A Promising Start

Saturday, March 15th, 2008

After having signed up for an Evernote beta invite a while ago, I finally received one this week.

Evernote is a next generation note taking service. What sets it apart from similar applications are the numerous ways of entering as well as retrieving notes. First of all there is the Evernote Website. It is simple and straightforward, and seems to be very responsive. You can create as many notebooks as you want. Each notebook acts like a folder that contains individual notes as files, and can be viewed using different perspectives (such as thumbnail view or list view), much like a native file browser application like Finder or Windows Explorer.

Notes can be entered and edited on the website, but there are several alternatives. For example, you can email a note to a special email address that is generated for you when you sign up. You can also use this mechanism to send notes from your mobile phone, using your provider’s SMS-Email gateway. However, I have been running into some technical issues when I attempted this from my mobile phone (I’m getting the following error message: “Your MSG could not be DELIVERED because InvalidPduContent”), so I need to look into this. Curiously, sending a picture via MMS worked just fine. Speaking of pictures: Evernote’s support for images is pretty amazing. It uses advanced text recognition to extract text from images, such that it becomes searchable. I have tested this with a low quality photo of a poster snapped from my mobile phone, and it worked as advertised. Very impressive!

You can also use a nifty bookmarklet that allows you to either submit an entire webpage to Evernote, or just the text that you have selected.

But perhaps most importantly, Evernote has a downloadable client app for both Windows and Mac. I have only tested the Mac client, which was released very recently. It seems to lag slightly behind its Windows counterpart in terms of features, but on the positive side it looks and feels like a proper Mac application rather than a quick port. It relies on a Sync feature to synchronize notes between the server and the client (either manually or in a configurable interval). Otherwise, the client offers pretty much the same functionality as the website. In addition, it comes with a clipping service that shows up in the menu bar (and registers some convenient keyboard shortcuts) and allows you to easily submit any copied text to the client, or even to clip a screenshot.

Evernote also has many ways to browse notes. It has a search box that allows you to find notes using full text search, but also using other criteria. For example, notes can be tagged (much like emails in Gmail), after which you can search for them by tag (or just click on the tag in the navigation bar). Notes can also be located via various attributes, such as creation or modification date, source (website, email, mobile, etc.), or whether or not they contain images or audio. This works from both the website or the native client. Evernote also has a mobile website, which I have not tested. This should be convenient when you need to look up a note while you’re on the road.

Overall, I am pretty impressed with Evernote. I have played with various note taking applications, and this comes very close to perfect in terms of features. I often have ideas that I need to capture, and right now I’m using a personal wiki for this purpose. However, I would prefer to work in a native application when possible, since this is generally more convenient. The combination of native client and website for Evernote is quite powerful, with a well-implemented synchronization mechanism. I just wish there were some wiki-like features, such as easy linking between individual notes. But the most important drawback is the lack of formatting options. The website only supports straight text entry, with no formatting at all. The Mac client supports rudimentary formatting (such as font, color, bold, italic, underline, alignment), but unfortunately this formatting appears to be lost when the note is uploaded to the website. The thumbnail view does show the properly formatted note, but the full view does not. And any edits on the website completely reset any formatting that might have been applied on the client. I don’t require any sophisticated formatting, but at the minimum I would need support bullet lists (which neither the Mac client nor the website supports), headings, and emphasis.

As it is right now, Evernote seems like a somewhat useful scratch pad to collect short notes, web clippings, etc. Particularly the mobile features might come in handy. With a bit of additional work, I think it could be extended to become a more comprehensive solution for organizing information, but right now I am going to continue using my wiki for this purpose.

If you would like to see it in action, there is a short Evernote Screencast.

iPhone SDK

Friday, March 7th, 2008

This morning, Apple finally announced details about the long-awaited iPhone SDK. The SDK is available for download starting today, and it sounds pretty intriguing!

It comes with a full application stack that includes a custom version of Cocoa (Cocoa Touch), and APIs to access all the iPhone specific features, including hardware-accelerated 3D graphics, the accelerometer, camera, contacts, as well as location-awareness. This sounds a lot more complete that I expected.

The tools side is covered very well, also: The SDK includes a custom version of the Xcode IDE, Interface Builder, Instruments (a profiler), and an iPhone Simulator, so you should be able to develop iPhone apps using essentially the same toolset as for regular OSX applications.

As expected, Apple will control the distribution for all iPhone applications through their App Store. Applications can be purchased and downloaded right from the phone, or via iTunes. Developers get complete control over the pricing, and Apple offers a 70/30 revenue split (70% for the developer), which seems pretty reasonable. Developers will also be able to make their applications available for free, in which case Apple takes no cut. It sounds like Apple will generally allow any application to be published, but there are some (mostly obvious) limitations (such as pornography, VOIP over cellular connections, or anything illegal).

The SDK itself is available for free on Apple’s developer website, although you have to have to register as an iPhone developer. However, in order to be able to submit applications to the App Store, developers need to join the $99 iPhone Developer Program. Apparently the developer program will initially be available on a limited basis, but I assume that most developers will be accepted in to the program later. Since the App Store is not scheduled to launch until June, this does not seem like a major issue, and in the mean time the iPhone Simulator that is included in the SDK looks to be a pretty exact copy of the actual iPhone, so this will have to do.

Users will need a firmware upgrade in order to run custom applications. I assume that this will be released around the same time as the App Store (although hopefully a bit sooner, for testing purposes). iPhone users will be able to upgrade for free, but iPod Touch users (like myself) will be charged a nominal fee (the exact amount has not been announced), supposedly due to differences in the way Apple accounts for the iPod Touch, since it does not come with a subscription plan.

The SDK download proved to be a major pain, since Apple’s website was hopelessly overloaded and it was impossible to even get the download to begin. I eventually got lucky and found the SDK on BitTorrent. Apple really should have made the 2GB download available on BitTorrent in the first place…

Anyway, I’m planning to play with the SDK a bit over the next few weeks or so. One thing I was hoping for is that the SDK might include support for RubyCocoa, since I’m not all that thrilled about the prospect of using Objective-C (or any C-derived language for that matter…), but based on my initial research things aren’t looking promising. Ruby is supported on jailbroken iPhones, so it seems like it should be feasible to support RubyCocoa as well. This will be the first thing

Oh, there were a few cool game demos as well, including an iPhone version of Spore! I am most interested in building my own iPhone apps, but I am also excited to see what kind of applications and games will be released by third parties. I am currently using several useful applications on my jailbroken iPhone Touch (such as an ebook reader and an unit converter), and it seems like it should be reasonably straightforward to port these to the official SDK, so I bet that most of these applications will be available soon, either for free or for a moderate price.

For more details, check out the following links:

Gentoo / AMD64 / Bluetooth

Thursday, February 3rd, 2005

After a bit of fiddling with masked ebuilds, I finally managed to get Bluetooth working with Gnome on my AMD64-based Gentoo system. In case you’re running into similar AMD64-related issues, please check out the following bugs I submitted to the Gentoo bug tracker:

(Hey, I got three sequential bug numbers) :)

The following bug is also relevant:

The HOWTO mobile phone, Bluetooth and GNOME Wiki page is also helpful. Note however that this is somewhat outdated. For example, the bluez-sdp package is deprecated and should no longer be used, as its functionality has been rolled into the other bluez packages.

After setting everything up, I was able to connect to my new Motorola V551 phone and transfer several files and J2ME applications from Gnome / Nautilus.

Leave a comment if you need further help.

sell your old cell phones

Monday, June 7th, 2004

I came across an interesting link on the wireless weblog: CellForCash.

They make it easy for you to sell your old cell phones by sending you a postage-paid box. The few phones that I have checked only sold for slightly above $10, but since they make it so easy, I may very well take advantage of this service to get rid of my old cell phones that are gathering dust in various corners and drawers…

Nokia ships impressive Nokia 7610 camera phone

Tuesday, June 1st, 2004

Nokia just announced that they have started shipping the impressive Nokia 7610 Series 60 camera phone. The price tag of somewhere over $600 seems a little hefty, but with service provider discounts this will probably be available for a lot less. The feature list certainly sounds awesome: 1 Megapixel camera, MIDP 2.0, 8MB internal memory plus 64MB MMC, tri-band, bluetooth, infrared, and USB connectivity, etc.

I would certainly love to have one of these to play with MIDP programming, although I’ve been pretty happy with my Nokia 3650 for this purpose. MIDP 2.0 would be nice, though.