Using CorePlot with Swift in iOS

Apple_Swift_LogoI just started working on a new iOS app right after the Swift announcement, and decided to try writing it in Swift. I needed to add some graphs to the app, and after looking at the options, I decided to give CorePlot a try. I wasn’t sure how things would work out with CocoaPods and a third party Objective-C library from a Swift app, but I was able to build something that works pretty well, so I’m going to outline how to do this with a quick sample app.

If you want to go straight to the code, my sample app is available on GitHub.

  1. The first step is to create your swift app. For our sample, we’re going to do a single view app, so create that in XCode, and set the default language to Swift
  2. Next, we’ll add CocoaPods as usual. Check out their site for more info how to install it, etc. But, once you have CocoaPods, go into your project dir and run:
    $ pod init
  3. This will give you a basic Podfile, which you’ll want to edit, to add the following line:
    pod 'CorePlot'
  4. Once you’ve added CorePlot to the Podfile, you can install CorePlot by running:
    pod install
  5. Now, you have to close the project in XCode and open up the newly created workspace for your project. The workspace file has a .xcworkspace extension, and should be in your project directory. Opening the workspace will give you access to your original project, plus all of the CocoaPods you’ve installed in the project.
  6. At this point, if you were writing an Objective C app, you’d be able to start adding CorePlot functionality to your app, but we need to do few things to get it working in Swift.
  7. Create a new header file in XCode, by going to File->New->File…, and select Header File (under iOS->Source). Call your header file <app>-Bridging-Header.h, where <app> is your app’s name. You can read more about bridging headers on Apple’s guide on interoperability.
  8. Add CorePlot to the header file, by adding this line:
    #import "CorePlot-CocoaTouch.h"
  9. Now, you have to tell XCode about the bridging header.
    • Click on the project in the Project navigator
    • Under the Targets heading in the left sidebar, make sure you click on your project’s name
    • Make sure the “All” view is enabled (as opposed to “Basic”)
    • Scroll way down to the “Swift Compiler – Code Generation” section toward the bottom
    • Under Objective-C Bridging Header, enter the name of your bridging header (e.g. <appname>/<appname>-Bridging-Header.h)
    • This should enable access to CorePlot from Swift, let’s try it out.
      Screenshot 2014-08-07 00.34.55
  10. Go into your storyboard and add a plain View object to your view controller. This view will be a placeholder for the graph we’re going to create. You should add proper layout constraints to make sure the view fills the whole screen without going off the screen. Here’s what mine look like (they are all set to zero):
    Screenshot 2014-08-07 00.42.41
  11. Set the view object to have a custom class, and set it to CPTGraphHostingView

    Screenshot 2014-08-07 00.33.37
  12. Create an outlet for the view in your view controller. Call it graphView.
  13. Add the following code to the viewDidLoad method of your ViewController class to create a simple pie chart:
    // create graph
    var graph = CPTXYGraph(frame: CGRectZero)
    graph.title = "Hello Graph"
    graph.paddingLeft = 0
    graph.paddingTop = 0
    graph.paddingRight = 0
    graph.paddingBottom = 0
    // hide the axes
    var axes = graph.axisSet as CPTXYAxisSet
    var lineStyle = CPTMutableLineStyle()
    lineStyle.lineWidth = 0
    axes.xAxis.axisLineStyle = lineStyle
    axes.yAxis.axisLineStyle = lineStyle
    // add a pie plot
    var pie = CPTPieChart()
    pie.dataSource = self
    pie.pieRadius = (self.view.frame.size.width * 0.9)/2
    graph.addPlot(pie)
    self.graphView.hostedGraph = graph
    view raw graph.swift hosted with ❤ by GitHub
  14. Add the CPTPlotDataSource protocol to the list of protocols that your ViewController implements. It should look something like this:
    class ViewController: UIViewController, CPTPlotDataSource {
  15. Add the CPTPlotDataSource methods. The samples below will create four sections in the pie graph, and the size of each section will be equal to its position plus one (i.e. 1, 2, 3, 4), so we’ll get a graph with some variety.
    func numberOfRecordsForPlot(plot: CPTPlot!) -> UInt {
    return 4
    }
    func numberForPlot(plot: CPTPlot!, field fieldEnum: UInt, recordIndex idx: UInt) -> NSNumber! {
    return idx+1
    }
    view raw data.swift hosted with ❤ by GitHub
  16. At this point, you should be able to run your app, and get a properly generated graph:
    Screenshot 2014-08-07 00.45.03

The code for my sample app can be found on GitHub here:

https://github.com/alwold/CorePlotTest

This shows the very basics of how to get up and running. There are some further caveats, especially with calling methods that involve parameters of the NSDecimal type. My solution for that was to add some Objective-C wrapper code. Hopefully, I can show how to do that in a future post.

Update: I have a new post describing how to deal with APIs that use NSDecimal here.

14 thoughts on “Using CorePlot with Swift in iOS

  1. Pingback: CorePlot, NSDecimal and Swift | Al's Blog

  2. brswllc

    When I try to run this, I get an exception. This is Xcode 6.1.1. I’m also trying to use the current version of coreplot 2.0 from git. Any ideas what I might be doing wrong?
    014-11-18 15:07:10.873 DnDGraphTest[11636:164655] -[Swift._NSContiguousString sizeWithTextStyle:]: unrecognized selector sent to instance 0x7fd0c1e333e0
    2014-11-18 15:07:10.884 DnDGraphTest[11636:164655] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[Swift._NSContiguousString sizeWithTextStyle:]: unrecognized selector sent to instance 0x7fd0c1e333e0’

    Backing up the stack trace, first place I see CorePlot code is:
    [CPTTextLayer sizeThatFits] + 318

    Reply
  3. Bertrand Delvaux

    Hello,

    Thank you for this very clear tutorial. I get an error message when I am trying to run the ‘pod install’ command:

    Downloading dependencies
    Installing CorePlot (1.5.1)
    [!] /bin/bash
    set -e
    dtrace -h -s framework/TestResources/CorePlotProbes.d -o framework/Source/CorePlotProbes.h

    sh: line 2: dtrace: command not found

    Reply
  4. myenfieldbike

    Looks like Pod is downloading only the 1.5.1 version and there is no 2.0 version of CorePlot in pod. Should I manually download and integrate with 2.0 and not through Pod?

    Reply
  5. alex

    tutorial is very clear but it does not work for me using xcode 6.3 (6D570)
    everything works fine as exepcted until right after 9
    Before anything else, i jsut wanted to check if i could still compile and run
    but unfortunately Pods-CorePlot > CPTAnimation.m fails to compile

    /Users/****/Projects/CorePlotTest/Pods/CorePlot/framework/Source/CPTAnimation.m
    /Users/****/Projects/CorePlotTest/Pods/CorePlot/framework/Source/CPTAnimation.m:359:42: Too many arguments to function call, expected 0, have 3
    /Users/****/Projects/CorePlotTest/Pods/CorePlot/framework/Source/CPTAnimation.m:379:42: Too many arguments to function call, expected 0, have 3

    Pods installed CorePlot 1.5.1 and i’m wondering if i shouldn’t use version 2.0, well basically anything that comes from master
    besides, ever since i have upgraded to xcode 8.2->8.3 swift language evolved and a lot of stuff in my swift code ended up broken. i’m guessing it is unrelated but who knows ?

    Reply
    1. Joe

      Here’s what worked:
      upgrade pod CorePlot to 1.6
      In AppDelegate.swift change:
      launchOptions: NSDictionary!
      to
      launchOptions: [NSObject : AnyObject]?
      on the other funcs in that file change: (to get rid of warnings)
      application: UIApplication!
      to
      application: UIApplication

      In file ViewController.swift change the return type of NSNumber! to AnyObject!

      Reply
      1. Joe

        Thank you Al for taking the time to illustrate the swift interface to the core plot framework.
        I needed to use a bar graph in an iOS swift app and looked at every cocoa pod that had “graph” or “chart” in it and found SwiftCharts, very new, but written in swift and very flexible.

  6. Abhi

    Can’t get it to work with XCode 6.3 .. same as Alex above.. exactly the same problem.. Anyone has any solutions/workarounds.. ???

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s