The Data Formatting Process

Whenever NSTableView displays its tabular data, it sends a [description] message to each data object. This converts the data into a human-readable form that is non-localized and unformatted by default. The converted data is then displayed in the appropriate column subview of NSTableView.

However, if NSTableView is to display its data in a specific format, an NSFormatter object must be assigned to the appropriate column subview. To do so using Interface Builder, first switch to the Text panel of the Cocoa palette, and drag and drop one of two NSFormatter objects from the palette and onto the desired subview (Figure 8). Select the formatter with a dollar symbol to instantiate an NSNumberFormatter. Otherwise, select the one with the calendar symbol to instantiate an NSDateFormatter. Make sure that correct column subview is highlighted before releasing the mouse button and thus binding the formatter to that subview.

Figure 9. Attaching an NSFormatter object in Interface Builder.

Once the appropriate formatter has been attached to the column subview, click to select the subview and choose Show Inspector from the Tools menu. Interface Builder then displays the configuration panel for the attached formatter (Figure 9). Enter the desired format strings into the fields provided by the panel. For more information on how to create a custom format string, consult one of the two Apple references at the end of this article.

Figure 10. Configuring the NSFormatter object in Interface Builder.

More sophisticated data formats can also be implemented by manually subclassing the NSFormatter class and binding the instance of the subclass to the table view widget. This approach provides a degree of control that is not possible with neither NSDateFormatter nor NSNumberFormatter. For instance, a custom formatter can attach an appropriate unit of measure to the formatted data. It can also be used to normalize the data with respect to a specific reference value.

To function correctly, the NSFormatter subclass must override the following inherited methods with the appropriate formatting code.

- (NSString *)stringForObjectValue:(id)anObj

Format the data contained in anObj to the appropriate human-readable representation.

Preferably, the class type of anObj is the same one used in the [stringForObjectValue:] message.

Like the data-source protocol methods, overriding the [getObjectValue:forString:errorDescription:] method is necessary only if the table view is to allow inline editing. Once the formatting code has been implemented, bind the custom formatter object to the appropriate column subview by using the [setFormatter:] message. For example, to bind the formatter object, aFormat, to the column subview, @"myCol", of aTable:

[[aTable tableColumnWithIdentifier:@"myCol"] setFormatter:aFormat];

Listing 4 is a example of a custom NSFormatter object that displays the incoming numerical data in terms of kilobytes. The [stringForObjectValue:] method takes the NSNumber parameter, aArg, and divides its numerical value by 1024. It then returns the converted result as a formatted numerical string with a 3-decimal place precision. However, if aArg is not an NSNumber, the method throws an NSInvalidArgumentException error.

The [getObjectValue:forString:errorDescription:] method receives the table cell data as an NSString. It converts the string to its numerical value and multiplies the value by 1024. It encapsulates the product result into an NSNumber and updates the parameter, anObj with the object. The method returns a YES to indicate a successful conversion; otherwise, it returns a NO.

Listing 4. A custom formatter that converts between bytes and kilobytes.