Creating an API FAST with Slim Framework

We develop API’s very regularly at 14 Oranges, being that almost every app we have developed requires some sort of back end data source. Developing an API is really not a difficult process but there are lots of little things to consider and building one from scratch is just not always the best use of your time. We do about 90% of our server side development in php and have over the past 15 years done everything from creating our own frameworks to using popular frameworks like Cake, laravel, symfony, zend and codeigniter. But up until this week I had always ignored Slim framework. I figured if I didn’t need all the bells and whistles on a project offered by a full featured framework, I would be better just going to my own toolset.

Andrew, one of our developers, mentioned recently he was using Slim for an api related project, so when I had to develop a really quick proof of concept for a client recently, I figured I would take the time to try it out and I thought I would put some notes down for other developers that might be curious. I ended up turning it into a presentation for our company and decided to share my findings here in this post.

I figured I would jump right in and install it, then look at a few examples, write some code and get it working before reading the documentation. I know, I know, RTFM, and I do … eventually. But I am a quick study and manuals more often than not put me to sleep.

My shortcut in this case paid off. I hadn’t gotten to reading the manual yet and my API was working as intended.. So I guess what I am saying is learning curve on Slim is really low.

I began by installing it via composer. You will have to have php installed first to complete this.

On my mac I created a new directory, opened up terminal and navigated to that directory and simply installed composer with this command.

curl -s | php

There are a couple routes to take next. You could install just the Slim framework and go from there or you could start with the slim-skeleton which basically does some of the initial setup for you and points you in the right direction. I went with the basic install but in retrospect I think installing the skeleton would be a better option.

I created my composer.json file containing the following:

   "require": {
     "slim/slim": "^3.0"

Lastly installed via composer with:

php composer.phar install

There you have it … took about 1 minute.

I created my index.php file and added some rewrite rules to ensure all requests were routed to this file in an .htaccess file. Lots of tutorials out there on how to do this so I will skip it. Inside the index.php file I had to require the autoload.php file that the Slim installation created, instantiate Slim and get going on my routing. Here is what that looks like.

 use \Psr\Http\Message\ServerRequestInterface as Request;
 use \Psr\Http\Message\ResponseInterface as Response;
require 'vendor/autoload.php';

The Slim Framework’s router is built on top of the nikic/fastroute component, and its fast and easy to use. Here is what my index.php file ended up looking like with my first route defined, a base route basically just saying you need to authenticate.

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '../vendor/autoload.php';
$app = new \Slim\App;
$app->any('/', function (Request $request, Response $response) {
   ->write("Welcome to the API. Please authenticate.")
   ->withHeader(''Content-type', 'application/json');
   return $response;


The use statements at the top of the script are bringing the Request and Response classes in. Slim framework now supports PSR-7, a PHP standard for HTTP messaging. We then setup $app to contain an instance of Slim and add a route. When adding a route to a Slim application you can choose an HTTP request method (POST, GET, PUT, OPTIONS, PATCH, DELETE) or as I have done in this case you can allow the listener to accept requests with any HTTP method.

Every HTTP request has a method that is typically one of:

OPTIONS – a request for information about the communication options available on the request/response chain identified by the Request-URI.

GET – retrieve whatever information (in the form of an entity) is identified by the Request-URI.

HEAD – identical to GET except that the server MUST NOT return a message-body in the response.

POST – used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI

PUT – requests that the enclosed entity be stored under the supplied Request-URI.

DELETE – requests that the origin server delete the resource identified by the Request-URI

PATCH – requests that the items in the enclosed entity be stored under the supplied Request-URI (not a wholesale update).

SLIM implements each of these methods and allows you to create your own custom methods as well. The methods are not strictly enforced by SLIM so you can work with them as you see fit. You could really throw the other devs for a loop by returning error code 69 on HEAD but I really would not recommend that.

The second parameter for the route method is the callback function which is being passed the PSR-7 request and response objects. A route can look at the request and manipulate the response as required then return the response. Once all of the logic and business stuff is done you run the $app and away we go.

So in about 5 minutes of coding we have our api’s first endpoint operational. Any request to the base url of our API will respond with a 200 HTTP status (default in Slim) with a JSON content type and a response body of ‘Welcome to the API. Please authenticate.’.

Obviously the API the way it stands now is not overly useful but all we have to do is add our routes corresponding to the endpoints of our API and we will have the job done. So here is a full API implementing a really simple Authentication endpoint. Obviously this is not something I would use in the real world but it is a great example of how fast and easy Slim is to use.

 use \Psr\Http\Message\ServerRequestInterface as Request;
 use \Psr\Http\Message\ResponseInterface as Response;
 require '../vendor/autoload.php';
$app = new \Slim\App;

 $app->post('/auth/',function (Request $request, Response $response) {
   $allPostVars = $request->getParsedBody();
   if($allPostVars['username'] !== "" || $allPostVars['password'] !==password_hash("superSecretPassword")) {
     $app->halt(403, 'Invalid Credentials.');
   }else {
     $token = password_hash ('SuperSecretToken');
     echo json_encode(array("status" => "success", "code" => 1, "token" => $token, "message"=> "App API Success" ));
 $app->get('/tickets', function (Request $request, Response $response) {
   if($token !== password_hash ('14Oranges')) {
     $app->halt(403, 'Invalid Token.');
   } else {
      $mapper = new TicketMapper($this->db);
      $tickets = $mapper->getTickets();
     $response->getBody()->write(var_export($tickets, true));
     return $response;

So there you have it. An Auth endpoint listening for username/passwordhash returning a token on success. A tickets endpoint sending back a list of tickets and verifying a valid token. All said and done very quickly. There are lots of useful features that I haven’t illustrated here but the documentation is good and the community is also pretty active so you can pretty easily find the answer you need.

Lots of handy helpers

Slim comes with a bunch of helper methods as well. Pretty self explanatory and easy to use. Here are a few examples.

$headers = $request->getHeaders();

$headerValueArray = $request->getHeader(‘Accept’);

$contentType = $request->getContentType();

$mediaType = $request->getMediaType();

$charset = $request->getContentCharset();

$length = $request->getContentLength();

$parsedBody = $request->getParsedBody();

$body = $request->getBody();


My Findings

Slim is small, fast and easy to use. I would definitely recommend trying it out if you are developing an api. Keep in mind that Slim takes a barebones approach to development, though. The routing is basic yet functional, but relies on the developer being able to extend it. The Slim team realize this, and have made it easy to do so, notably with middleware and their use of Dependency Injection.

Templating is available too. Slim ships with support for Twig and PHP-View, but there are many other options as well. There are some very useful organizational tools such as route hierarchy and groupings allowing you to keep a complex API well organized.

I am not about to get Slim Framework tattooed across my back at this point but I know a few guys that might!.image00

Nexus 5 to Nexus 5X Notification Sound Transfer

Just got a new Nexus 5X and set it up last weekend. To my surprise, all the notification sounds I was using on my Nexus 5 had changed even though they had the same name. I started googling around to see how to transfer them and didn’t find any single article on how to do so, so I decided to take upon myself to provide some instructions. I also promise that you won’t need to root your device or do anything that requires more geek brain cells than you currently have.

Before you start, here is what you will need:

  1. A Nexus 5X connected over wifi or data
  2. A Nexus 5 connected over wifi or data
  3. A dropbox account (note that Google drive or others could do) and the dropbox app installed on both phones. Login to your dropbox account on both phones. Now we use dropbox and wifi/data to transfer files on and off devices mostly for 2 reasons. 1. The Nexus 5X comes with a USB-C connector and I can’t find a USB-C to USB-A cable to be bought anywhere. All sold out or coming soon. My iMac doesn’t see my Nexus 5 when connected over USB for some reason.

And now the steps

Step 1 Getting the old files off your Nexus 5

  1. To transfer the sounds off your old Nexus 5, you need to access the /system/media/audio/notifications folder on your device. I’ve tried a few file manager apps and settled on the aptly named File Manager (not to be confused with the dozen other apps also named File Manager).
  2. Once you have File Manager installed, you need to make your way to /system/media/audio/notifications. Best way to do so is to click the little home icon at the top and then make your way to the folder.Screenshot_20151105-071240
  3. Once you are there, you will see a list of .ogg files which are the notifications sound files. Find the one that you would like to transfer. You can tap on it to hear it to confirm it is the one you want.
  4. Do a long press on it so that a little dialog comes upScreenshot_20151105-071421
  5. Select the Send option and then select “Add to Dropbox”. Select a dropbox folder and click Add.
  6. Wait a minute or so for Dropbox to do its synchronize.
  7. Go onto dropbox and rename the file to use a different name. I simply append “Old to the file name. So OldAriel.ogg for example.
  8. Migrate over to your Nexus 5X and start the dropbox app. Find the file you just put there Screenshot_20151105-074815
  9. On the right hand side, you should see a little down arrow. Tap on it
  10. Scroll (pan) down and tap the Export option and select Save to device. It should default to the Downloads folder. If not, make your way there.
  11. Tap Save
  12. Now for some reason File Manager doesn’t handle copying files to the Notifications folder properly. Likely a permission issue. You need to use this File Manager. Complete fluke I found this out actually.
  13. By default, that app presents a nice UI which doesn’t help you do much. Tap the hamburger menu at the top left and select Internal Storage
  14. Navigate to /root/sdcard/Download
  15. Find the file and do a long press on it until the list shifts to the right and the file has a checkbox beside it. Screenshot_20151105-073936
  16. Tap the dot menu at the top right and select Copy To
  17. Tap on Internal Storage
  18. Navigate to /root/sdcard/Notifications folder
  19. Tap OK. The file is now saved there.
  20. Go to your settings apps and select notifications sounds.
  21. You will now see two files with the same name. One of them is the stock notification, the other one will be the sound you just copied.
  22. Enjoy.

The 14 Oranges Guide to Planning a Mobile App


Working in the App development field for the past 6 years, we have found that many of our customers come to us with an idea but have no idea where to start. We work to help them understand the process for developing their business and their app. App development, as with most businesses, starts with a market and an idea. Taking that idea and turning it into an app can be a daunting task. If you follow some basic steps in the planning process, it can be greatly simplified and much more effective for your audience.

The planning process begins with the Business Model, moves through to establishing app requirements and a minimum viable product and finishes with a phased plan to managing the project.

The words Apps - Where to Begin asking if you need help choosing the best app programs or software to put on your mobile device or smart phone, or how to develop applications

The words Apps – Where to Begin asking if you need help choosing the best app programs or software to put on your mobile device or smart phone, or how to develop applications

Business Model

We have many customers approach us with nothing more than an idea, most people don’t consider a business plan. You certainly do not need to have all the details (pricing, categories, options) sorted out, but when planning an app, you should consider how you intend to make money with it. You are more than welcome to create an app for philanthropic reasons, but we can’t all be Bill Gates so it’s imperative you think about how to make money from your app as one of the planning steps. Is your app going to be a paid for app, free, freemium, or a subscription service? There are multiple options to consider so let’s explore them below.

Apps Available for Purchase

The first and most basic model that was available on the various app stores was to provide apps for purchase. Users pay a one time fee (ranging from $0.99 to $999) to purchase the app with the bulk of apps being at the lower end of the spectrum. Now with that being said, Apple probably didn’t do anyone any favors by pushing the typical price of apps to be in the $0.99 range compared to the more typical $20 to $50 range that is very common for desktop apps. Now in some rare cases like Angry Birds, the $0.99 model worked like magic, but in general, selling apps for $0.99 can be very difficult considering that developing an app for a smartphone can be just as time consuming and costly as a desktop application. Moreover, with Apple and Google taking 30% of your proceeds, it makes getting a decent return on investment quite difficult. In order to make a $0.99 model work, your app idea must be earth shattering or you must be prepared to spend a huge amount of money on advertising to achieve global outreach and market wide penetration. Viral apps exist out there but those are few and far between and should not be counted on.

In App Purchases / Freemium

A variation of the straight purchase model is to offer the app for free (or even a small price) and offer additional features in the app as “In-App purchases”. Perhaps your app is restricted to a few records, a few basic features, and the more elaborate capabilities are offered for purchase. That model allows customers to pay for exactly the features they need and can maximize your revenues (if I recall my Microeconomics 101 course properly). The one factor to consider is that it can make testing the app a bit more involved as you have to test for all the different combinations of features. Once again, with In-App purchases, you are subject to the 30% store taxes.

This model is a very cost effective way to attract potential customers; however, be ready to expect somewhere in the 3% to 5% conversion rate for the paid features.

74_application management

Membership/Subscription Model

With most apps requiring some type of cloud service, one of the most effective revenue models is the membership or subscription model. In this model, users are asked to pay a monthly, yearly, and/or per consumption fee to use your app. With this model, you actually have two choices. You can rely on In-App purchases, allowing users to purchase items using the built in In-App purchase mechanisms provided by Apple or Google to pay for their subscription, but again at a cost of 30% to your bottom line. Another option to curb that “tax” is to create your own subscription service using one of the many payment providers (Stripe, Beanstream, Moneris). Now it does involve more work as you typically would need to include a website / user portal for users to manage their accounts and buy the service but that additional work/cost can quickly be recovered with the improved margins on your sales. One thing that you must be aware of is that in order for an app using your own subscription payment service to be approved by Apple, there must not be a single way for users to learn about and proceed with payment within your app. If there is a way, Apple will find it and your app will be rejected. They are quite good at protecting their revenue sources, which seems obvious given their staggering profits.

Basically, your customers will need to learn about your service outside of the app. The one exception to this rule is if the content they are subscribing to is consumed outside of your app. For example, maybe you are selling a gym membership within your app. The app acts as a point of sale but in the end, you are not using your app to consume your membership.


The last form of generating money from your app is advertising. Advertisers will pay to show their ads to your user base and there are a few ways to approach this scenario. One option that is quite popular with start up apps is to have a one or more ‘app sponsors’. When the app is being developed some of the costs can be offset by selling sponsorship opportunities. Often this will result in a banner type ad being placed in a prominent place within the app. These sponsors can be transitioned into long term advertisers once the app is live. A second approach to generating advertising revenue is to incorporate a third party advertising network into your app. These ad networks will automate the display of ads within your app, paying you for clicks or views of the ad depending on the arrangement. If your app is likely to generate lots of users and frequent use, this may be the optimal solution for you.

Some key factors when exploring Advertising Revenue Models are:

  • App traffic – how many users and how often will they use your app
  • Demographics – the more focused the demographics of your audience the more targeted the ads resulting in higher click through rates

Ad revenue can be a very effective method of generating money from your app, the rates for clicks or impressions are very low, all things considered, so the traffic needs to be there for it to make sense.


After putting together your thoughts on the business model, the next thing to consider when planning out the app itself is the apps functionality. Creating a list of these requirements will be very helpful in scoping the work involved in completing the app. Software development can be extremely complicated and what might appear to be small features could actually involve hours of R&D.

One simple example of this would be time based triggers on iOS. For example if you want your app to perform a task every 15 minutes this would logically seem like a simple task. In reality, this is quite challenging to complete.

Here are some questions to ask when putting together your requirements list:

  • What platforms will be supported? (iOS, Android etc..)
  • What devices types will be support? (Phone, Tablets, Phablets)
  • Will the user need to login?
  • Will the app need to know the user’s location?
    • If so, how precise and how often
  • Will push notifications be required?
  • Will payments be accepted inside the app?
  • Will the project require a website?
  • Will the project require an admin panel?

If you are finding it difficult to write requirements, try sketching things out on paper, screen by screen or use a software tool like Balsalmiq to help you design this. This will help you visualize the pieces of the app from which the requirements will be derived.


Minimum Viable Product (MVP)

Once you have created the requirements list for all the possible features to complete your dream app, it is important to be pragmatic and break out the Minimum Requirements to take your app to market. Time and money are the key factors at play. First Mover Advantage can be a huge factor in app rollout and defining an MVP allows you to get to market quickly while managing your costs.

Phased Approach

Most apps, once distilled, focus on a single concept surrounded by nice to have features that help manage and utilize the concept. Approaching app development using a phased approach has a slew of advantages.

Budget management is the obvious first advantage to a phased approach. If you develop the MVP and take the app to the market, you can often begin generating revenue which can then be reinvested to the features development.

Another advantage of a phased approach is the ability to build to your customers wishes. You can poll your user base, look at comments in the app store and build in the features your customers are asking for. Sometimes this will line up with your original concepts but often times the users will ask for things your team had not even thought of which is a fantastic way to connect with your customer base.

Adding features in a phased approach can also help with user engagement. Users can be notified of new features and that can bring them back into the app on a more steady basis. Many apps struggle to get users to come back to their apps on a regular basis so new features and updates can give users a reason to return.


Once you have worked your way through the planning process outlined above, you are ready to get started. Think about the business model, define your requirements, decide on an MVP and put a plan in place.  Don’t forget to reach out to your targeted customer base and ask them what features and ideas they want to see implemented in an app.  Most app users are tech savvy and would have some brilliant insight into your plan.  If you follow this simple process you will be ready to sit down with your development team and get the project underway.
If you need help or have questions during your app planning process, contact 14 Oranges.


How to Use JSONKit for iOS and the Rotten Tomatoes API

Here is a short tutorial on how to use JSONKit and since it is best to have a tutorial with a real life example, we decided to show how to use it with the Rotten Tomatoes API. Now we know that using JSONKit is rather easy but we felt a tutorial could still help a few out there so here goes.

UPDATE: The article had a mistake. It used to say to use the objectWithData and objectWithString methods of JSONDecoder and should have said to use the NSData objectFromJSONData and NSString objectFromJSONString methods. Thanks to reakinator for pointing that out. The example project with source code had the correct API all along. The article has now been corrected. Apologies for the slip.

Here are the steps you will need to do before getting started:

  1. Go to Rotten Tomatoes API site and apply for an account and a key. It is free to do so. Without a key, you won’t be able to get responses from their API.
  2. Download JSONKit source code from Github

Note: We completed those steps with XCode 3.2.6 against 4.3 iOS SDK.

Using JSON Kit
Using JSONKit is super easy. What you need to do:

  1. Once you have downloaded and unzipped the zip file obtained in the preparation steps above, you will need to drop JSONKit.h and JSONKit.m in your project.
  2. Then import JSONKit.h” in your .m files where ever you need to parse a JSON response
    import "JSONKit.h"
  3. Whenever you have JSON data that you need to parse (more on how to get some later), you just use the objectFromData method like so

    NSData* jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];

    NSDictionary *resultsDictionary = [jsonData objectFromJSONData];

    Alternatively, if you have your data in string form, you can use the following:

    NSDictionary *resultsDictionary = [jsonString objectFromJSONString];

  4. Once you have your dictionary, you can inspect it using the objectForKey method to get objects out of it.

Note: JSONKit is free but is licensed under BSD license or Apache License Version 2. Make sure to follow their licensing terms as specified in the source code.

Using Rotten Tomatoes API
The Rotten Tomatoes API allows you to do queries so you can obtain information about movies such as “year of release, runtime, cast, posters, audience scores, critics scores, reviews, and a slew of other data. Typically the steps to get what you want are

  1. Search for the movie name
  2. Find the movie in the list of results and get its id
  3. Do specific query using the id

Easy enough right? Let’s see the details:

  1. Search for the movie name:
    You can use the to make your search request (where YOURKEY is the API key you obtained in the preparation steps and MOVIENAME is the movie you are looking for. The response you will get should be something like:

    -movies: [
    +{ … }
    +{ … }
    +{ … }
    +links: { … }
    link_template: "{search-term}&page_limit={results-per-page}&page={page-number}"

    Note that we “shrunk” the actual movie match details down to +{ …} for clarity. To read this, you need to understand that NUMBEROFMATCHES is the number of results that you got. For example, searching for Toy Story, will results in 7 matches (Toy Story 3, Toy Story 2, Toy Story, Toy Story & Toy Story 2 in 3D Double Feature, so on).
    Now to make that request you would do it like so:
    NSString* theURL = [NSString stringWithFormat:@"",YOURKEY, SEARCHTERM];
    NSError* err = nil;
    NSURLResponse* response = nil;
    NSMutableURLRequest* request = [[[NSMutableURLRequest alloc] init] autorelease];
    NSURL*URL = [NSURL URLWithString:theURL];
    [request setURL:URL];
    [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
    [request setTimeoutInterval:30];
    NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];

    Note: We chose to use a synchronous request here for simplicity. In reality, you likely want to use asynchronous methods so that your code isn’t stuck on waiting for Rotten Tomatoes to respond.

    Now when you use objectFromData method to put that into an NSDictionary, any terms that have the answers right away, will be returned as an object.
    For example:
    id: 770672122
    title: “Toy Story 3”
    year: 2010
    Doing [resultsDictionary objectForKey:@"id"] would return an NSNumber with the movie id while [resultsDictionary objectForKey:@"title"] would return an NSString with the movie name. Similarly, you would get NSNumber for the @”year” key. Now the API sometimes return the year in quotes; therefore, you do need to test to see if the object returned was an NSNumber or an NSString. In the cases where the responses include a [, it means you are getting an array. For example:
    -movies: [
    Means that doing [resultsDictionary objectForKey:@"movies"] would return an NSArray of NSDictionary.

  2. Find the movie in the list of results and get its id
    Now finding the movie in the list will depend on your search criteria. We used the year to match. The code looks like this:
    NSString *aYear = yearField.text;
    NSDictionary *results = [jsonString objectFromJSONString];

    NSArray *movieArray = [results objectForKey:@"movies"];

    // Search for year to match
    for (NSDictionary *movie in movieArray)
    NSNumber *year = [movie objectForKey:@"year"];

    if ([[year stringValue] isEqualToString:aYear])
    NSNumber *ID = [movie objectForKey:@"id"];
    // Now use this ID for the next query

  3. Do specific query using the id
    Once you have obtained the id, you can then do another JSON request using the id. The URL will be of this form:”

That’s basically it. Rotten Tomatoes provides extensive documentation on their API here.

We are providing the code for this example here. Note that you will need to put in your API key at the top of RottenTomatoesJSONViewController.m class.

UPDATE:: We are doing an informal poll to see the iOS verstion distribution amongst our readers. Head over to our statistics post and let us know which version you are currently using.

How to Use Core Plot for iOS

Ever wanted to have a plot inside your iOS application?
Core Plot Example Screenshot
Well CorePlot could be what you need. It provides basic plotting capabilities like scatter plots or bar plots with ability to configure the style and color of the plot and also have multiple plots included in a graph. The project is open sourced and available on Google code and since the instructions / examples currently available are not up to date with the latest version (0.2.2) we thought it would be good to share our observations.


  1. First thing is that the latest version now includes a pure installer. Most of the instructions you will see are currently for the “manual” install version. We were able to install using the installer so I recommend you use that (the file). The zip file contains Core Plot Installer.pkg (standard package installer). You simply need to run that.
  2. Once you have finished the install, open the project you want to include a plot to
  3. Add to your project’s .PCH file: #import <CorePlot/CorePlot.h>
  4. Open Project -> Edit Project Settings and for All Configurations:
    1. Add to Additional SDKS: /Library/SDKs/CorePlotSDK/${PLATFORM_NAME}.sdkNote that’s the default location where the SDK is installed, if you installed somewhere else, you need to adjust that to match.
    2. Under Compiler Version, change your C/C++ compiler to LLVM GCC 4.2.
    3. Add to Other Linker Flags:-ObjC -all_load -lCorePlot
  5. Add the QuartzCore framework to the project. Right click on Frameworks | Add > Existing Frameworks. Under iOS 4.2 SDK, select QuartzCore.framework and add that.
  6. You are now ready to add a CPXYGraph to your application.

Note that we completed those steps with XCode 3.2.5 against 4.2 iOS SDK.

Using Core Plot
Here are the important classes to use:

  1. CPXYGraph: That’s the main graph class where the plots will be written to.
  2. CPGraphHostingView: That’s a special view design to host CPXYGraph. One trick you will need to do is that whichever UIView you will want to have the graph in will need to be changed to a CPGraphHostingView in Interface Builder using the Identity Inspector. The class won’t show up in the list so you have to type in manually. Note this class used to be called CPLayerHostingView so old instructions may reference this.
  3. CPXYPlotSpace: That defines the drawing area for the plots. You can define the start position (say -10) and the length (say 20) to give you how big your plot is going to show (say from -10 to 10) and you do that for X and Y using the xRange and yRange properties.
  4. CPScatterPlot: That class is to create a scatter plot.
  5. CPBarPlot: That class is to create a bar plot.
  6. CPXYAxisSet: That class represents the axis in the plot. You use the properties xAxis and yAxis to decide how they are going to look like. You can set major intervals, ticks per intervals, line style, and label offset amongst other things.
  7. CPPlotSymbol: That class defines the style/color for the dots on the plot

Basic Concepts:
To have a graph shown, you need to include one CPXYGraph in your view controller. Also CPXYGraph makes use of the CPPlotDataSource protocol so include that in your interface definition. For example:
@interface TestCorePlotViewController : UIViewController <CPPlotDataSource>
CPXYGraph *graph;

and now in your code you can instantiate your graph like so:
graph = [[CPXYGraph alloc] initWithFrame:YOURFRAME];
Once you have a graph, you can start adding plots to it. Once your graph is completed, you can assign it to the CPGraphHostingview hostedGraph property and you are all set.

The methods from the CPPlotDataSource is what is going to return the data points. You can return the number of records for each plot using the -(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot method and the actual values for each data point using the -(NSNumber *)numberForPlot:(CPPlot *)plot field:NSUInteger)fieldEnum recordIndex:(NSUInteger)index method.

Now most of what was learned here was obtained from the initial example obtained here
Now unfortunately that app hasn’t been updated in a while so it won’t compile out of the box. Here is the updated code: CorePlotExample

If CorePlot is too basic for you, I suggest having a look at KeepEdge or at iPhone Chart since they provide commercial plotting libraries. We have no experience with them however so we cannot provide comments.

UPDATE:: We are doing an informal poll to see the iOS verstion distribution amongst our readers. Head over to our statistics post and let us know which version you are currently using.