field-theory.org
the blog of wolfram schroers

PowerPlot: Business reporting for iPhone, iPod Touch and iPad

This article is about the design of the PowerPlot library for native business reporting and scientific charts on iOS. It reviews and discusses the design of the library and its key components.

Table of contents:

Introduction
Design of PowerPlot
Conclusion

Introduction

The basic design is based on the MVC pattern, with specific view and data classes provided. Each PowerPlot chart is an instance of class WSChart which is a subclass of UIView. In the following the basic design of such a chart is reviewed. It is shown how everything fits together. An understanding of these concepts is needed unless you want to only use the default designs.

Topics are the chart view, the Model–View–Controller (MVC) design pattern, and the organization of the chart elements: the view controllers. Finally, simple factory methods allow to generate charts out of the box with minimal coding.

Design of PowerPlot

A WSChart consists of several subviews which are subclasses of WSPlot. Each WSPlot is associated with an instance of class WSPlotController and an instance of class WSData. WSData provides the data the specific subview displays and the controller links both the views and data components. The controller also provides the coordinate systems that relate the data and the way they are presented.

The chart view

The basic element of a PowerPlot chart is the view WSChart which is a subclass of UIView and can be embedded in a window using either Xcode's .xib-files or programmatically. A WSChart contains one or more individual plots, each handled by an instance of WSPlotController.

Structure of WSChart

A WSPlotController is responsible for referencing the plot view, the associated data and the coordinate system. Functionality includes alerting/highlighting, data bindings and managing gestures recognizers. See the examples for alerting, data bindings, and zooming/scrolling and selecting data. Note that this is not the same as a user interface view controller, but rather an abstraction to combine several data model objects and view objects in a chart.

Internally, an instance of WSChart acts like an array of WSPlotControllers. When it comes to drawing the individual plots, the plots are drawn in the order of their indices. In this way, the ordering can be used to control how plots cover each other.

Charts almost always contain multiple plots. Typically, one has the coordinate system (an instance of WSPlotAxis) and one or more data sets (instances of other subclasses of WSPlot).

The MVC design pattern

PowerPlot is based on the Model–View–Controller (MVC) design. The idea of MVC is to separate and modularize independent parts of the program logic.

The “Model” handles (i.e., receives, computes, stores etc.) all the data, but does not know how it will be presented to the user. In many business applications the data is transferred to the mobile device using RESTful web services. In PowerPlot this data model is handled by the class WSData. An important feature of this class is that it can be serialized, deserialized and copied. In addition, the data model can store style information that is relevant for the user. Examples are the colors of bars in the bar chart or the colors and fonts of nodes in a graph. The WSData class can be initialized with standard C-style arrays, making it compatible with any framework that handles data on iOS. See this example for more details on what WSData can do and how to use some more advanced features.

The “View” does the actual presentation of the data. Each view is a subclass of WSPlot which is in turn a subclass of UIView and added to a WSChart as a subview. The following types of views are available:

WSPlotAxis
Draw the coordinate system axis, the correponsding labels and optionally also a grid. This plot is used at least once in almost all charts. It does not use any data model – if one is present in the controller, it will be ignored.
WSPlotBar
Draw bars in Y-direction.
WSPlotData
Draw data points, lines and fillings between the X-axis and the data. Optional features include spline-interpolations to smoothen data, shadows and error bars in X- and Y-direction.
WSPlotDisc
Draw circles and ellipses based on data points with errors and (optional) error correlations.
WSPlotGraph
Draw graphs (nodes and connections) on the canvas. Graphs may not need to be combined with a WSPlotAxis to look good.
WSPlotRegion
Draw filled regions of any shape. These typically can be used for contours and for error bands.
WSPlotTemplate
Template for custom subclass of WSPlot.

The third component is the controller. In most MVC-designs, the program-specific logic resides in the controller, making it highly non-portable. In PowerPlot, the controller design will require users to customize the components, but usually not to subclass or augment the controller itself.

More on the controllers

Each WSPlotController has four key components: The “view”, the “dataD” model and two instances of WSCoordinate, defining the abscissa via “coordX” and the ordinate via “coordY”.

Structure of WSPlotController

The “dataD” property defines the data object. This is almost always an instance of WSData and usually not shared with other views (unless they plot the same data with different coordinate systems or methods).

The “view” is typically a subclass of a WSPlot. It is possible to use other custom views or even standard Cocoa views. In that case it is not necessary to define the data or coordinate properties. Some views (like the WSPlotAxis view) do not require “dataD”.

An important property of WSPlotController is the ability to have its own coordinate system. Therefore, plots with different coordinates can be directly combined in a single chart. The WSChart instance does not have any coordinate system on its own, instead each WSPlotController has the properties coordX and coordY that define its individual coordinate system. These coordinates are retained by each individual plot controller.

Note that this is an optional feature. PowerPlot does not enforce distinct coordinates and in most cases they are not necessary. In fact, most factory methods will simply instantiate a single coordinate system only and use it for all plot controllers inside the plot.

Another property of a plot controller are the axis locations, corresponding to the properties axisLocationX and axisLocationY. These locations are important for some plot types like the coordinate axis, bar plots and line plots with fills. The controller is responsible for the placement of the axis when the view's frame changes (e.g., if the device is rotated) or animations, scrolling or pinching gestures change the coordinate system. The developer needs to decide if the X- and Y-axis should stay at their relative screen positions, at their absolute locations or at specific data coordinate values.

The use of a capital “D” at the end of objects and methods refers to the coordinate system being used: If the coordinate system refers to “data” coordinates, a “D” is appended, otherwise it is missing. As some objects can return information either in “data” or in “bounds” (of the view) coordinates, this distinction allows developers to easily see what they are dealing with.

Factory methods for simple charts

In many cases the full power and flexibility of PowerPlot is not needed. Instead, one can simply use so-called “factory methods” which are implemented as categories of WSChart. These categories implement class methods that return autoreleased instances of WSChart that has all code in place to present default charts to the user. Of course, it is still possible to customize or augment these charts, if needed. Most examples in the examples section of PowerPlot start from such an auto-generated chart and customize features or add on to them.

The default categories that implement these factory methods all contain Factory in their filenames and are thus found easily. Additional and/or customized factory methods are available on request.

Conclusion

PowerPlot is a versatile, flexible and powerful library that has been specifically designed for iOS, i.e., the iPhone and the iPad. It has a set of simple default factory methods and allows extensive and versatile customization of charts. For other options with different advantages and drawbacks please refer to this overview article and for a specific step-by-step tutorial see this article.

A complete listing of example codes can be found here.