Blog

bi1

Developing iOS Apps with Custom Charting

Introduction

After developing multiple iOS apps (SAP Note Viewer for iPad and iPhone, iOS CRM) I recently stumbled across one of my biggest hurdles so far (aside from learning Obj. C!) in creating a Sales dashboard within a native application. Charting and Graphing in business applications, including SAP, is a everyday necessity providing users, managers and CEO’s a visual representation of important, monotonous and a downright boring set of data. Dashboards, charts and graphs have become a common place within organizations and new releases of Business Objects BI 4, are making these easy to deploy, user friendly, interactive and can be very helpful in making game time decisions. Utilizing these visualizations from a mobile platform is something which is being actively developed (Business Explorer for iPhone for example) but currently there are very few plugins/frameworks/controls or libraries which make adding custom visualizations to your XCode project easy. A good example of some great looking charts in iOS would be Roambi. In my quest to solve this challenge I came across a solution which allowed me to mashup javascript and objective c creating a solution which is working fairly well so far and felt like some others developing on this “newish” platform might find helpful. While my solution does not come close to being comparative to products like Roambi, it does provide some tricks to making charting fairly simple for anyone wanting to do so. This post will be Part 1 of the series covering the charting portion and Part 2 will run through the process of actually retrieving data from SAP using web services.

Finding a framework

When I first had the requirement of building a sales dashboard within iOS I started out with Core-Plot but was quickly frustrated with the difficult installation and fairly complex methods to implement a basic pie chart. Some of the other issues included a small user base (but helpful google groups forum), little documentation with examples on implementation and so on. After a week of struggling, I decided to take a alternative route in using UIWebViews to display charts written using Javascript within my native application. It is a slightly unconventional method and does have its own drawbacks, some of them being:

-          Non-native look and feel

-          Difficulty with touch interaction (sometimes buggy)

-          Depending on charting framework some apps will require internet connectivity to render.

Some Advantages:

-          Extremely quick and easy to implement.

-          Highly configurable look

-          High re-usability

-          Generally a large user or support base

-          Open Source

-          Many are Free

While working on this project, I evaluated many different Javascript Charting libraries, including the Google Chart API, Flot, Highcharts (not free for commercial use), gRaphael to name a few. Here is a nice compilation of the charts and some comparisons. http://www.splashnology.com/blog/javascripts/290.html . After a considerable amount of testing I ended up picking Highcharts. The nice aspect to Highcharts was its wide range of charts, a very basic way of providing data to the chart and the charts would still work “offline”. It was also open source and free for non-commercial use ($80 for a basic license). The product can be used on iOS devices and supports the touchscreen. If you are looking to create very specialized visualizations I would recommend checking out InfoVis Toolkit which includes icicle, Treemaps, force directed and even sunburst type charts. After testing all the packages in a little demo app I was very close to using flot, since it had the easiest input of data. But no interaction was supported on the iPad. gRaphael was next, it supported touch interaction and data input was also easy but it did not have the wide range of graphs and themes that Highcharts did. So in the end I pulled the trigger on highcharts and started coding away.

Another good option was the Google Chart API which has a really simple online chart wizard and would be quick and easy to implement since it uses their servers to create the chart and simply returns an image to the device window (in our case the UIWebView). The biggest downside was limited interactivity and the fact it required a internet connection to render the charts. With a local javascript option, data could be stored in a cache or db and update when the datasource becomes available.

Developing the application

Here are a couple screenshots of the application displaying the charts (note all data is randomized).

Some Basic Chart testing with flot ….

Finished App (more pictures at bottom)

*** All data is randomized and not relevant ***

How to add and use the Javascript libraries in XCode

Here is a simple view of how I handle the code and data within XCode.

1. Download the Javascript reporting package from your preferd chart site. In my case: http://www.highcharts.com/download

2. Add or import the files into XCode resources. (I suggest creating a group called JS).

3. When adding a resource to XCode it will generally be marked as being needed to be compiled. Ensure that the files are not listed as being “Compiled”. The easiest way is to simply drag the files from Targets -> Your Project Name -> Compiled Sources  into Targets -> Your Project Name -> Copy Bundle Resources.

4. Create a test html file or simply import one from your HighChart (or any other javascript chart library) examples folder. In my case I name it hcpie.html

5. Ensure that any file references in the <script> tags do not recurse or move into any folder (even if they are in one in your project). e.g.

RIGHT = <script type=”text/javascript” src=”highcharts.js”></script>

WRONG = <script type=”text/javascript” src=”../JS/highcharts.js”></script>

6. Create a UIWebView within Interface Designer and link it to your view (in my case I named it chart1). e.g.

@interface FirstViewController : UIViewController {
IBOutlet UIWebView *chart1;
}

@end

 

7. Simply reference the HTML example file when loading.

- (void)viewDidLoad {

NSString *pathOfFile = [[NSBundle mainBundle] pathForResource:@”hcpie” ofType:@”html”];
NSString *htmlText = [NSString stringWithContentsOfFile:pathOfFile encoding:NSUTF8StringEncoding error:nil];

NSURL *baseURL = [NSURL fileURLWithPath:pathOfFile];

[chart1 loadHTMLString: htmlText baseURL:baseURL];

[super viewDidLoad];

}

 

This is a very basic overview of how to get started with charts, from here your imagination – and business requirements – are your only restriction :)

Always Online?

Another option would be to actually generate the html file and its data within another package such as ASP.NET, PHP and be hosted on a internal server (IIS, Apache, etc.) but still using the javascript visualization controls. A downside to this is it requires your app to have constant connection with your servers or corporate networks via the LAN or VPN. However, a big advantage to this is that you could create and deploy your native app to the users and simply update some very basic HTML files with your data when it becomes available. In this case you might want to start considering a HTML5 app versus native. (Another whole debate all together!)

Data Retrieval

This overview does not cover retrieving data from your datasource but generally a webservice pulling data into a local SQLite DB would be the best bet. (or a basic plist if the data was simple enough). If you are interested in web services and doing some testing I would recommend checking out the ES Workplace which is a awesome test bed for SAP Web services. (Anyone else looking forward to Project Gateway as much as I am?) Part 2 will cover pull some basic data from ERP and displaying it within a chart, so stay tuned for more.

Conclusion

As you can see (if you made it this far!), this somewhat “hybrid” approach to visualizations on iOS devices is not perfect but a really good solution if you do not have the time, budget or resources for developing your own set of charting controls for the platform.

Still with me?

If you made it this far you are probably pretty serious about considering this … here are a couple other things I have learnt along the way:

Basically, I split my html file into 2 parts – a header and footer, this allows me to insert the data from xcode using my preferred datasource (web service) without having to write excessive amounts of javascript, html and css within the “display” method calls. Building the string is done by looping through my record source dataset and then appending the header, data and footer together to create the continuous stream of HTML/Javascript and CSS required to render the chart. I might be doing this in a different manner to others and it also might not be the most efficient, but it is the easiest method I have found. (Share yours?). String concatenation in Obj. C is tedious to say the least especially after dealing with multiple other programming languages where a simple +, & or . will do the trick.

A couple more screenshots