I 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.
- 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
- 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
- This will give you a basic Podfile, which you’ll want to edit, to add the following line:
pod 'CorePlot'
- Once you’ve added CorePlot to the Podfile, you can install CorePlot by running:
pod install
- 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.
- 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.
- 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.
- Add CorePlot to the header file, by adding this line:
#import "CorePlot-CocoaTouch.h"
- 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.
- 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):
- Set the view object to have a custom class, and set it to CPTGraphHostingView
- Create an outlet for the view in your view controller. Call it graphView.
- Add the following code to the viewDidLoad method of your ViewController class to create a simple pie chart:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters// 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 - Add the CPTPlotDataSource protocol to the list of protocols that your ViewController implements. It should look something like this:
class ViewController: UIViewController, CPTPlotDataSource { - 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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersfunc numberOfRecordsForPlot(plot: CPTPlot!) -> UInt { return 4 } func numberForPlot(plot: CPTPlot!, field fieldEnum: UInt, recordIndex idx: UInt) -> NSNumber! { return idx+1 } - At this point, you should be able to run your app, and get a properly generated graph:
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.
Pingback: CorePlot, NSDecimal and Swift | Al's Blog
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
Adding the -ObjC linker flag fixed it.
Getting the error : “Missing Argument for Parameter ‘frame’ in call”
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
Thanks, you saved my day!
works great
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?
Your article helped me a lot. Thanks for sharing. 🙂
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 ?
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!
Oh and add:
frame: CGRectZero
as an argument on the CPTPieChart() call
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.
Can’t get it to work with XCode 6.3 .. same as Alex above.. exactly the same problem.. Anyone has any solutions/workarounds.. ???