Multi-select tables and the Three20 framework

Introduction

At Nixwire, I’m using the Three20 Project as a foundational framework for an application where I needed to create a multiple-selection UITableView, so that I could perform an operation on all table rows selected by the user. The UITableView control does not support multiple-row selection without custom programming. Matt Gallagher provides a helpful example on how to create a multi-select table on his Cocoa with Love blog. Using Matt Gallagher’s example as a starting point, I made the multi-select control work in the context of the Three20 framework, and share my learnings here.

The Three20 Project was created by Joe Hewitt of Facebook. The components in Three20 were originally built as part of the Facebook iPhone application, then Joe Hewitt made the components generic and open-sourced the framework. Three20, currently characterized as “alpha quality” by the project owner, provides an excellent set of reusable UI and plumbing components for iPhone applications. Being in an alpha development state, documentation is scant and there can be a learning curve, but the value provided by the framework makes it worth the effort to learn. Components provided by the Three20 framework include:

  • A photo viewer control that behaves similar to Apple’s Photos app
  • A message composer that behaves similar to Apple’s Mail app
  • TableViewControllers that are able to load their content from the internet
  • URL-based intra-app navigation, allowing URL binding to resources within your application
  • Persistent state on UI controls

Solution detail

Controller setup

First, we need to set up the controller. Our controller, NXWMultiselectTableViewController, inherits from TTTableViewController, and is registered with the Three20 framework’s NavigationCenter by associating it with the URL “tt://nxwMultiselect”.

	TTNavigationCenter* nav = [TTNavigationCenter defaultCenter];
	nav.mainViewController = self.navigationController;
	nav.delegate = self;
	nav.urlSchemes = [NSArray arrayWithObject:@"tt"];
	...
	[nav addView:@"nxwMultiselect" controller:[NXWMultiselectTableViewController class]];

Once the controller is mapped to the URL, any Three20 control can be configured to navigate to the controller’s view with click actions. For example, to navigate to our multiselect table from another table’s cell, you would set up the URL property on the cell’s TableField to the desired URL:

[[[TTTableField alloc] initWithText:@"Multiselect" url:@"tt://nxwMultiselect"] autorelease]

Then, when clicking on the table cell, the Three20 framework loads the appropriate controller by calling the loadView method on the controller. Sweet!

Sequence diagram for “checking” an item

Once the controller is loaded, the user may “check off” cells by tapping them. The sequence diagram below shows how the various classes interact to “check off” a multi-select table row while in edit mode.

Sequence diagram: Select table row to check

Sequence diagram: Select table row to "check"

  1. User selects the row. The UITableView sends tableView:didSelectRowAtIndexPath: method call to the TableViewDelegate.
  2. TableViewDelegate adds index path to SectionedDataSource’s selectedIndexPaths array.
  3. TableViewDelegate sends tableView:prepareCell:forRowAtIndexPath: method call to the SectionedDataSource.
  4. DataSource prepares the TTImageTableField’s defaultImage property to the checked PNG image.
  5. DataSource sends a setNeedsLayout method call to the TableFieldCell, which prepares the cell for rendering.

Items to note

  • Minimal drawing code. Aside from a few lines of code in the TableFieldCell’s layoutSubviews method, there is no code required to draw the cell; the TTImageTableField Three20 class takes care of the drawing.
  • Customizable data source. The data source used in this example uses a hard-coded array of names; in order to display real data, you would need to set up the data source with the appropriate data through the TableViewController’s createDataSource method.
  • URL-based navigation. After binding the controller to the desired URL in the TTNavigationCenter, the control can be accessed by URL within the application.
  • Searchable table. The source includes the ability to filter the table results by typing one character at a time. While this capability is beyond what I’ll cover in this post, it’s worth studying my example to see how search is implemented. Pay attention to the TTSearchBar that is set up in the TableViewController’s loadView method, as well as the SectionedDataSource’s tableView:search: method and rebuildItems method.

Screenshots of the solution

TTTableView in non-edit mode with no items selected:

TTTableView in non-edit mode

TTTableView in non-edit mode

TTTableView with some items selected:

TTTableView with items selected

TTTableView with items selected

Confirmation of items selected:

Confirmation of items selected

Confirmation of items selected

Source code

Source code for this example is available here. The example requires the current version of the Three20 framework (as of 11 May 2009).

iPhone - Emerging Frameworks

This coming Saturday, May 16th, I’ll be discussing the new tools, code, and frameworks that are coming out of developing iPhone community. I’ll be focusing on some of the tools that the team at Nixwire has started actively using such as:

The talk will center around what this means for developers - how it can speed development, what each framework offers, challenges in keeping up with such a evolving space, and how all of us can contribute and participate.

Afterward, we’ll have an active Q&A session, and if it’s still going after a bit, maybe we’ll hit a pub nearby to continue the fun.

Reblog this post [with Zemanta]

The Future of Enterprise Software

We’ve arrived at another inflection point for enterprise software, and the future is bright (and mobile).

Looking back at the past, a period of significant growth followed game-changing developments adopted by the corporate community.  Against the backdrop of the worst economic downturn in modern history, this is the case beginning effectively now.

A buzzword soup of terms — SOA, SaaS, WS — is materializing into a tangible offering — cloud computing.  Startups get it.  Amazon, IBM, Oracle, Google get it.  Big business is getting it.

Enterprise Software Turning Points

IBM announced further developments in their Blue Cloud initiative here and here.  Oracle’s portal demonstrates that they are aggressively pursuing cloud computing via both the storage and software models.

The drivers of moving to the cloud are:

  • Increased outsourcing and specialization leading to an overall reduction in-house IT spending
  • Explosion of data-intensive applications and the increasing demand for metrics and business intelligence (BI)
  • Increased enterprise comfort-level with outside vendors and data services
  • Advancement and adoption of grid computing, web services / SOA, virtualization
  • Increasing demand for the mobile enterprise

Corporate IT has already embraced outsourcing and virtualization, so it makes sense to take the next logical step towards specialization — cloud computing.  Free yourself of managing zero value-add IT infrastructure and focus on your core business by leveraging services like AWS/EC2 to achieve pure business goals.  Worrying about server requisitioning, provisioning, configuring software, and bandwidth is simply a complex and unnecessary distraction.

Moving to the cloud enables quick ramp-up and ramp-down utilization of what would typically take significant man-hours to do internally.  Quick provisioning of servers, web servers, applications, application servers; pay for what you use during the lifetime of a project; no capitalized infrastructure; shut it all down when the project runs it’s useful lifespan is what it is and will be all about.

Enterprise adoption tends to trend at about a 2-3 year lag from introduction, so we’re starting to see the first wave of real cloud computing adoption, and expect to see full adoption beginning in 2010 through 2011.

What does this mean for mobility?

With the adoption of both public and private clouds by the enterprise, this will free up capital for enterprise mobility projects and also enable them by easing data access outside the four walls.  As IT infrastructure costs decrease by efficient use and specialization — cloudsourcing — of applications, this money can be plowed into mobility projects to really take advantage of distributed data access, further reducing the cost of doing business.

Mobilizing your field workers and freeing your desk workers delivers increased business transaction economy from sales, manufacturing, and delivery to billing, maintenance, and reporting.  Total integration to the enterprise via mobile devices and applications — far beyond the current contacts, email, phone applications of today will further drive enterprise cloud adoption (which will in turn fuel more mobile adoption).

The exciting enterprise inflection point we’re living through today signals a fundamental change to the way business will be conducted.  The rise of cloud computing and mobility will match the internal and external expectations of your staff and customers.

I’ll be laying out the best practices here to identify your key applications to mobilize and strategies to ensure successful rollout and adoption.

Speed Workflow with iPhone Simulator Cropper

Oliver at http://www.curioustimes.de has created a nice tool that speeds marketing material creation for the iPhone by cropping images right out of the simulator instead of using the Xtools Organizer.
The benefit here is that the images can be saved directly as JPGs and the status bar (top 20px) can be automatically removed. Great little tool!
You can find the iPhone Simulator Cropper here.

Consider an Analytics Package for Your iPhone App

Launching an app in the App Store is a great achievement, but you’ll be flying blind with just the sales metrics provided by iTunes Connect.

Inevitably, there will be issues you’ll want to track, real-time user metrics, and a broader understanding of the device population that you’re deployed to.

There are a couple of startups tackling this problem, and I definitely suggest you check out their lightweight SDKs and integrate one with your application. There’s a great similarity across what they are all offering — a few logging methods and a web-based dashboard reporting the results. Most even take advantage of CoreLocation to report back the geographic distribution of your user base.

We’ve been using mobclix to accomplish this, and in general, it’s a good offering. All of this is new, so I wouldn’t get too carried away with your expectations, but this begins to fill the void that Apple has so far not addressed.

One of our home dashboards in mobclix:

Mobclix Dashboard

gives us an instant breakdown of how many users on what devices and what their primary means of connection (wifi, carrier, none) is. We’ve chosen not to track their location, though, as this application doesn’t use CoreLocation

So, when planning your rollout, considering the easy integration of one of these offerings:

How to Add Images to the iPhone Simulator

Adding images to the iPhone Simulator Library is important if you want to do extensive testing with the UIImagePickerController and your source type is UIImagePickerControllerSourceTypePhotoLibrary, or you just want your images to be displayed.

The camera is not available on iPod touches, so this is even more applicable if that’s one of your targeted devices.

There’s a good post about this on ofCodeAndMen()

The trick is to drag your image onto the simulator which will launch Safari. Then, just tap and hold the image to save to your Simulator’s library.

Getting UIImage to work with NSCoding encodeWithCoder

Out of the box, UIImage doesn’t support the NSCoding protocol which means it won’t automatically serialize if you stuff these in a dictionary or object and archive (using NSKeyedArchiver for example). The easy solution is to convert this into an NSData object which does support the protocol:

//convert from PNG to NSData, other method available for JPG
NSData *imageData = UIImagePNGRepresentation(imageToArchive);
[self.currentItem setValue:imageData forKey:@"image"];
 
//after the archived object is unarchived, you can retrieve the image like this
NSData *imageData = [currentItem valueForKey:@"image"];
if(imageData){
       UIImage *image = [UIImage imageWithData:imageData];
}

Without doing this, and trying to archive a UIImage will just result in:


-[UIImage encodeWithCoder:]: unrecognized selector sent to instance

Pretty simple. The key is the helper method UIImagePNGRepresentation found in the UIKit Function Reference.

More Than Just Guidelines

The iPhone Human Interface Guidelines are more than just that — it is essential for you to understand them in order to ensure that your app will be approved for sale in the App Store.

From Apple:
“Applications must adhere to the iPhone Human Interface Guidelines as outlined in iPhone SDK Agreement section 3.3.5.”

Consider this important guideline in the Table Views, Text Views, and Web Views section of the iHIG:

“Table views provide feedback when users select list items. Specifically, when an item can be selected, the row containing the item highlights briefly when a user selects it to show that the selection has been received. Then, an immediate action occurs: Either a new view is revealed or the row displays a checkmark to indicate that the item has been selected. The row never remains highlighted, because table views do not display persistent selected state.”



The easy part to miss when implementing your own View Controller is “The row never remains highlighted”.

In your own custom UIViewController subclasses, you’ll want to address this within the

- (void)viewWillAppear:(BOOL)animated UIViewController delegate method.

Given a UITableView member property, theTableView, you can make sure the selected row gets deselected after popping the previous View Controller:

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
 
//deselect any selected rows
NSIndexPath *selectedRowPath = [theTableView indexPathForSelectedRow];
[theTableView deselectRowAtIndexPath:selectedRowPath animated:YES];
...
}



Treat the guidelines as the law of the land, and you and your users will attain App Store nirvana.

Solid, Comprehensive iPhone State-of-the-Market Overview

From the Amazing iPhone site, the team over there has put together a very thorough review of the iPhone market including history, opportunity, and developer requirements current through the end of 2008. Worth a read, especially for developers interested in understanding the emerging smartphone marketplace.

The Amazing iPhone Report