Core Plot Tutorial: Getting Started

The Nuggets translation Project

Translator: llp0574

Proofreader: Yifili09, CDpath

Note: This tutorial has been updated by Attila Hegedus for iOS 9 and Swift 2.2. The original tutorial was written by tutorial team member Steve Baranski.

If you’ve ever wanted to include charts or graphics in your app, you’ve probably considered the following two options:

  1. Write their own.Write all the drawing code using a framework like Core Graphics or Quartz. However, this obviously takes a lot of work.
  2. Buy one!Buy an image likeShinobiControlsSuch a business-oriented framework. This may save you time, but it costs money.

But what if you don’t want to take the time and effort to write from scratch and spend that much money? This is where the third option comes in: use the open source library Core Plot!

Core Plot is a 2D plotting library for iOS, Mac OS X and tvOS. It uses Apple frameworks like Quartz and Core Animation, has comprehensive test coverage, and is released under a relatively loose BSD license.

In this tutorial, you’ll learn how to use Core Plot to create pie and bar charts, while also implementing some cool chart interactions!

To get started, you need to have Xcode 7.3 installed and have some knowledge of Swift, Interface Builder and Storyboards. If you don’t know much about these topics, you should check out some of our other tutorials before moving on.

This tutorial also uses CocoaPods to install some third-party dependent libraries. If you’ve never used CocoaPods before, you should also check out our tutorial.

An introduction to

In this tutorial, you will create an App that displays currency rates at regular intervals. Download the introductory project for this tutorial from here, unzip it and open SwiftRates. Xcworkspace.

The project’s key classes are in the App folder and its subfolders, which include:

  • DataStore.swiftThis is one fromFixer.ioRequest the help class for currency exchange rate data.
  • Rate.swiftThis is a model that represents the currency exchange rate at a given date.
  • Currency.swiftThis is a model that represents the type of money. The supported currency types are defined inResources/Currencies.plistIn the water.
  • MenuViewController.swiftThis is the first view controller that’s shown when an app launches. It lets users choose one currency as the benchmark and then two controls.
  • HostViewController.swiftThis is a container view controller that controls the presentation based on its staging statePieChartViewControllerorBarGraphViewControllerThe content of the. It also goes to check fromDataStoreThe requested exchange rate data, because they’re also going to be presented in this view controller.
  • PieChartViewController.swiftThis controller will show the exchange rate on a given date in pie chart form. Of course you have to make it happen first!
  • BarGraphViewController.swiftThis controller will display exchange rates in a bar chart over several days. Pie charts are a piece of cake when you learn how to draw them! See what I did? Come on, this is really interesting!) ; ]

Build and run see this tutorial introduction project in action.

Click Get Rates to navigate to the view controlled by the HostViewController and then you can switch segments. The app really doesn’t have many features yet… ; ]

Time to really start plotting with Core Plot!

Install the Core Plot

First you need to install Core Plot, the easiest way to do this is through CocoaPods.

Add the following line to your Podfile, after the line pod ‘SwiftDate’ :

Pod 'CorePlot', '~ > 2.1'Copy the code

Open Terminal, CD into your project root directory, and run Pod Install.

After the installation is complete, build the project.

Is that correct? Great, now you can use Core Plot any way you want, thanks to CocoaPods. :]

If you encounter any errors, try updating cocoapods with sudo gem Install Cocoapods and then running Pod Install again.

Create a pie chart

Open the PieChartViewController. Swift and add the following introduction:

import CorePlot
Copy the code

Next, add the following property:

@IBOutlet weak var hostView: CPTGraphHostingView!
Copy the code

The CPTGraphHostingView is responsible for “hosting” a chart or graph. You can think of it as a “graphic container.”

Then, add the following class extension after the curly braces at the end of the file:

extension PieChartViewController: CPTPieChartDataSource, CPTPieChartDelegate {

  func numberOfRecordsForPlot(plot: CPTPlot) -> UInt {
    return 0
  }

  func numberForPlot(plot: CPTPlot, field fieldEnum: UInt, recordIndex idx: UInt) -> AnyObject? {
    return 0
  }

  func dataLabelForPlot(plot: CPTPlot, recordIndex idx: UInt) -> CPTLayer? {
    return nil
  }

  func sliceFillForPieChart(pieChart: CPTPieChart, recordIndex idx: UInt) -> CPTFill? {
    return nil
  }

  func legendTitleForPieChart(pieChart: CPTPieChart, recordIndex idx: UInt) -> String? {
    return nil
  }
}
Copy the code

You will provide data for a Core Plot chart via CPTPieChartDataSource, and you will get all the events for user interaction via CPTPieChartDelegate. As the tutorial progresses, you’ll fill in these methods.

Create a managed view of the chart

Go ahead and open main. storyboard and select the PieChartViewController window.

Drag out a new UIView on this view, change its class to CPTGraphHostingView, and connect it to hostView.

Add constraints on each direction of the view to fill the parent view and make sure no constraints are set on margins:

Set a background color that you like. I used a gray color with a opacity of 92%.

Now, back to PieChartViewController swift in viewDidLoad () behind to add the following method:

override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() initPlot() } func initPlot() { configureHostView()  configureGraph() configureChart() configureLegend() } func configureHostView() { } func configureGraph() { } func configureChart() { } func configureLegend() { }Copy the code

This is just in time to set up the drawing strategy after the subview is rendered. This is where you first set the frame size for your view. Next you will need to configure the drawing strategy.

Each method in initPlot() represents a stage for setting the drawing strategy. This keeps the code maintainable.

Add the following line to configureHostView() :

hostView.allowPinchScaling = false
Copy the code

This line of code disables pinch and zoom gestures on the pie chart, which determines whether the managed view responds to kneading gestures.

Next you need to add a diagram to hostView. Add the following code to configureGraph() :

// 1 - Create and configure the graph let graph = CPTXYGraph(frame: Hostview.bounds) hostview.hostedgraph = graph graph.paddingLeft = 0.0 graph.paddingTop = 0.0 graph.paddingright = 0.0 Graph.paddingbottom = 0.0 graph.axisSet = nil // 2 - Create text style let textStyle: CPTMutableTextStyle = CPTMutableTextStyle() textStyle.color = CPTColor.blackColor() textStyle.fontName = Textstyle. fontSize = 16.0 textStyle.textAlignment =.center // 3 - Set graph title and text style graph.title = "\(base.name) exchange rates\n\(rate.date)" graph.titleTextStyle = textStyle graph.titlePlotAreaFrameAnchor = CPTRectAnchor.TopCopy the code

The code for each part is broken down below:

  1. First you create an instance of CPTXYGraph and specify it as the hostedGraph of hostView. This links the chart to the managed view.

    The CPTGraph contains everything you would see in a standard chart or graph: edges, headings, drawing data, axes, and legends.

    By default, CPTXYGraph has an inner margin of 20 in each direction. This is not good for our project, so you can explicitly set the inside margin to 0 in each direction.

  2. The next step is to set the text style for the icon title by creating and configuring a CPTMutableTextStyle instance.

  3. Finally, set the title and style for the diagram instance you just created. You also need to specify the title anchor as the upper boundary of the view.

Build and run the app, and you should see the title of this chart displayed on the screen:

Draw the pie chart

The headline looks good, but you know what’s gonna be even better? Actually see the pie chart!

Add the following code to configureChart() :

// 1 - Get a reference to the graph let graph = hostView.hostedGraph! // 2 - Create the chart let pieChart = CPTPieChart() pieChart.delegate = self pieChart.dataSource = self pieChart.pieRadius = (min(hostView.bounds.size.width, HostView. Bounds. The size, height) * 0.7) / 2 pieChart. Identifier = graph. The title pieChart. StartAngle = CGFloat (M_PI_4) SliceDirection =. Disarray by piechart. labelOffset = -0.6 * piechart. pieRadius // 3 - Configure border style let BorderStyle = CPTMutableLineStyle() Borderstyle.linecolor = cptcolor.whitecolor () borderStyle.lineWidth = 2.0 pieChart.borderLineStyle = borderStyle // 4 - Configure text style let textStyle = CPTMutableTextStyle() textStyle.color  = CPTColor.whiteColor() textStyle.textAlignment = .Center pieChart.labelTextStyle = textStyle // 3 - Add chart to graph  graph.addPlot(pieChart)Copy the code

Here’s what this code does:

  1. You first get a reference to the diagram you just created.
  2. And then instantiate oneCPTPieChart, set its proxy and data source to the view controller itself, and configure some of its appearance properties.
  3. Then configure the border style for the chart.
  4. Configure its text style.
  5. Finally, add the pie chart to the chart you just referenced.

If you rebuild and run your app now, you won’t see any changes… Because you also need to implement the proxy and data source for the pie chart.

First, replace the current numberOfRecordsForPlot(_:) method with the following:

func numberOfRecordsForPlot(plot: CPTPlot) -> UInt { return UInt(symbols.count) ?? 0}Copy the code

This method determines how many pieces (parts) are displayed on the pie chart, and it will display one piece (parts) for each tag.

Next, replace numberForPlot(_:field:recordIndex:) with the following:

func numberForPlot(plot: CPTPlot, field fieldEnum: UInt, recordIndex idx: UInt) -> AnyObject? { let symbol = symbols[Int(idx)] let currencyRate = rate.rates[symbol.name]! . FloatValue Return 1.0 / currencyRate}Copy the code

The pie chart uses this method to get the “total” value of the currency symbol indexed as recordIndex.

You should note that this value is not a percentage value. Instead, the method calculates the currency exchange rate relative to the base currency: the value of the 1.0 / currencyRate returned is the exchange rate of an alternative reference currency for what a unit of the base currency is worth.

CPTPieChart will look at calculating the percentage value for each slice, which ultimately determines how large the slice is.

Replace dataLabelForPlot(_:recordIndex:) with the following line:

func dataLabelForPlot(plot: CPTPlot, recordIndex idx: UInt) -> CPTLayer? { let value = rate.rates[symbols[Int(idx)].name]! .floatValue let layer = CPTTextLayer(text: String(format: "\(symbols[Int(idx)].name)\n%.2f", value)) layer.textStyle = plot.labelTextStyle return layer }Copy the code

This method returns the label of the pie slice. The expected return type, CPTLayer, is somewhat similar to CALayer, but CPTLayer is more abstract, works on Mac OS X and iOS, and provides additional plotting details for Core Plot.

Here, create and return a subclass of CPTLayer, CPTTextLayer, to display the text.

Finally, replace sliceFillForPieChart(_:, recordIndex:) with the following code to add the color of the fragment:

func sliceFillForPieChart(pieChart: CPTPieChart, recordIndex idx: UInt) -> CPTFill? {
  switch idx {
  case 0:   return CPTFill(color: CPTColor(componentRed:0.92, green:0.28, blue:0.25, alpha:1.00))
  case 1:   return CPTFill(color: CPTColor(componentRed:0.06, green:0.80, blue:0.48, alpha:1.00))
  case 2:   return CPTFill(color: CPTColor(componentRed:0.22, green:0.33, blue:0.49, alpha:1.00))
  default:  return nil
  }
}
Copy the code

Build and run, and you should have a nice pie chart:

Wait a minute… Legend!

The diagram looks pretty good, but adding a legend should make it even better. Next you will learn how to add a legend to this diagram.

First, replace configureLegend() with the following:

func configureLegend() { // 1 - Get graph instance guard let graph = hostView.hostedGraph else { return } // 2 - Create legend let theLegend = CPTLegend(graph: graph) // 3 - Configure legend theLegend.numberOfColumns = 1 theLegend.fill = CPTFill(color: CPTColor.whiteColor()) let textStyle = CPTMutableTextStyle() textStyle.fontSize = 18 theLegend.textStyle = textStyle // 4 - Add legend to graph graph.legend = theLegend if view.bounds.width > view.bounds.height { graph.legendAnchor = .Right  graph.legendDisplacement = CGPoint(x: -20, y: 0.0)} else {graph. LegendAnchor =.bottomright graph. LegendDisplacement = CGPoint(x: -8.0, y: 8.0)}}Copy the code

You also need to provide legend data for each shard.

To provide the data, replace legendTitleForPieChart(_:recordIndex:) with the following: legendTitleForPieChart(_:recordIndex:)

func legendTitleForPieChart(pieChart: CPTPieChart, recordIndex idx: UInt) -> String? {
  return symbols[Int(idx)].name
}
Copy the code

Build and run, and you’ll have a “legend” diagram.

Create a bar chart

It looks like you’re already an expert on pie charts, but it’s time to get a bar chart!

Open up BarGraphViewController and add the following line:

import CorePlot
Copy the code

Next, add the following line:

@IBOutlet var hostView: CPTGraphHostingView!
Copy the code

Just like the pie chart, the managed view will host the bar chart presentation.

Next, add the following attributes:

var plot1: CPTBarPlot!
var plot2: CPTBarPlot!
var plot3: CPTBarPlot!
Copy the code

Three properties of type CPTBarPlot are declared, which correspond to each currency shown in the chart.

Notice that there are also three IBOutlet tags and three IBAction methods defined, which you can see in the storyboard.

Finally, add the following class extension to the end of the file:

extension BarGraphViewController: CPTBarPlotDataSource, CPTBarPlotDelegate {

  func numberOfRecordsForPlot(plot: CPTPlot) -> UInt {
    return 0
  }

  func numberForPlot(plot: CPTPlot, field fieldEnum: UInt, recordIndex idx: UInt) -> AnyObject? {
    return 0
  }

  func barPlot(plot: CPTBarPlot, barWasSelectedAtRecordIndex idx: UInt, withEvent event: UIEvent) {

  }
}
Copy the code

This is very much like creating a pie chart: the bar chart is provided with data via CPTBarPlotDataSource, and user interaction events are captured via CPTBarPlotDelegate. You just copy and paste.

Configure the chart managed view again

Again, just like when you created the pie chart, you need to add the managed view through the interface builder.

Go back to Main.storyboard and select the BarGraphViewController window.

Drag out a new UIView on the view, change its class to CPTGraphHostingView and connect its output to the hostView in the controller.

Use the Utilities\Size Inspector (the scale TAB) to update its frame as follows:

X = 0, Y = 53, Width = 600, Height = 547

Add constraints to it and all adjacent elements, making sure no margin constraints are set.

Finally, set a background color that you like. Again I used a gray color with 92% opacity.

Draw a bar chart

Now that the UI is complete, it’s time to draw a bar chart.

First of all, going back to BarGraphViewController, you need a pair of constant properties. Add the following before the other attributes:

Let BarWidth = 0.25 let BarInitialX = 0.25Copy the code

You also need a helper function to calculate the highest rate. Add the following paragraph after updateLabels() :

func highestRateValue() -> Double {
  var maxRate = DBL_MIN
  for rate in rates {
    maxRate = max(maxRate, rate.maxRate().doubleValue)
  }
  return maxRate
}
Copy the code

Next, add the following method to highestRateValue() :

override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() initPlot() } func initPlot() { configureHostView()  configureGraph() configureChart() configureAxes() } func configureHostView() { } func configureGraph() { } func configureChart() { } func configureAxes() { }Copy the code

Does it look familiar? Yeah, these are exactly the same structures as before.

Add the following line to configureHostView() :

hostView.allowPinchScaling = false
Copy the code

Since you don’t need pinching, you should disable it again.

Next, add the following lines to configureGraph() :

// 1 - Create the graph let graph = CPTXYGraph(frame: hostView.bounds) graph.plotAreaFrame? .masksToBorder = false hostView.hostedGraph = graph // 2 - Configure the graph graph.applyTheme(CPTTheme(named: kCPTPlainWhiteTheme)) graph.fill = CPTFill(color: Cptcolor.clearcolor ()) graph.paddingBottom = 30.0 graph.paddingLeft = 30.0 graph.paddingTop = 0.0 graph.paddingright = 0.0 // 3 - Set up styles let titleStyle = CPTMutableTextStyle() titlestyle.color = cptcolor.blackcolor () Titlestyle. fontName = "helveticaneue-bold" titlestyle. fontSize = 16.0 titlestyle.textalignment =.center graph.titleTextStyle = titleStyle let title = "\(base.name) exchange rates\n\(rates.first! .date) - \(rates.last! Date) "graph. The title = title graph. TitlePlotAreaFrameAnchor =. The Top graph. TitleDisplacement = CGPointMake (0.0, -16.0) // 4 -set up plot space let xMin = 0.0 let xMax = Double(rates.count) let yMin = 0.0 let yMax = 1.4 * highestRateValue() guard let plotSpace = graph.defaultPlotSpace as? CPTXYPlotSpace else { return } plotSpace.xRange = CPTPlotRange(locationDecimal: CPTDecimalFromDouble(xMin), lengthDecimal: CPTDecimalFromDouble(xMax - xMin)) plotSpace.yRange = CPTPlotRange(locationDecimal: CPTDecimalFromDouble(yMin), lengthDecimal: CPTDecimalFromDouble(yMax - yMin))Copy the code

Here is a breakdown of the code logic:

  1. First, instantiate oneCPTXYGraphIt’s actually a bar graph, and it relates it tohostView.
  2. And then declare aSimple whiteDefault theme and set left and bottom margins to show the XY axis.
  3. Then set the text style, chart title, and title position.
  4. Finally, configureCPTXYPlotSpace, which maps the coordinate system of the device to the coordinate system of the diagram. For this chart, you are plotting three exchange rates using the same coordinate system. However, it’s also possible that every bar graph has coordinatesThe separation of. You also assume a range of maximum and minimum exchange rates in the coordinate system. In later tutorials, you will learn how to automatically adjust the size of the space without setting the range in advance.

Now that you’ve created the diagram, it’s time to add some drawing methods! Add the following code to configureChart() :

// 1 - Set up the three plots plot1 = CPTBarPlot() plot1.fill = CPTFill(color: CPTColor(componentRed:0.92, Green :0.28, Blue :0.25, alpha:1.00) plot2 = CPTBarPlot() plot2.fill = CPTFill(color: CPTColor(componentRed:0.06, Green :0.80, Blue :0.48, alpha:1.00) plot3 = CPTBarPlot() plot3.fill = CPTFill(color: CPTColor (componentRed: 0.22, green: 0.33, blue: 0.49, Alpha :1.00) // 2 - Set up line style let barLineStyle = CPTMutableLineStyle() barlinestyle.linecolor = Cptcolor.lightgraycolor () barlinestyle. lineWidth = 0.5 // 3 - Add plots to graph guard let graph = hostView.hostedgraph else { return } var barX = BarInitialX let plots = [plot1, plot2, plot3] for plot: CPTBarPlot in plots { plot.dataSource = self plot.delegate = self plot.barWidth = BarWidth plot.barOffset = barX plot.lineStyle = barLineStyle graph.addPlot(plot, toPlotSpace: graph.defaultPlotSpace) barX += BarWidth }Copy the code

Now look at what the above code does:

  1. Instantiate each bar chart and set their fill color.
  2. Instantiate an object that represents the outer border of each bar graphCPTMutableLineStyleInstance.
  3. Provide “common configuration” for each bar chart. This configuration includes setting the data source and proxy, width and relative position of each bar chart in the coordinate system (left and right), line style, and finally, adding the coordinate system to the chart.

You can’t see the bar chart yet, but you can build the app to verify that everything compiles correctly so far.

In order to actually see the data displayed in the bar chart, you need to implement proxy methods that provide the data needed for the chart.

Replace numberOfRecordsForPlot(:_) with the following line:

return UInt(rates.count ?? 0)
Copy the code

This method returns the total number of records that should be displayed.

This replaces numberForPlot(_:field:recordIndex:) :

If fieldEnum = = UInt (CPTBarPlotField. BarTip. RawValue) {if the plot = = plot1 1.0} {return if the plot = = plot2 {return rates[Int(idx)].rates[symbols[0].name]! .floatValue } if plot == plot3 { return rates[Int(idx)].rates[symbols[1].name]! .floatValue } } return idxCopy the code

The value of CPTBarPlotField.BarTip indicates the relative size of the bar chart. You can use the reserve property to calculate the exchange rate when you need to retrieve the data, and the recordIndex corresponds to the position of the interest rate.

Build and run, and you should see something like this:

It’s almost done! But notice that there’s nothing yet that says what each axis means.

To fix this, add the following to configureAxes() :

// 1 - Configure styles let axisLineStyle = CPTMutableLineStyle() AxisLinestyle. lineWidth = 2.0 AxisLinestyle. lineColor = CPTColor.blackColor() // 2 - Get the graph's axis set guard let axisSet = hostView.hostedGraph? .axisSet as? CPTXYAxisSet else { return } // 3 - Configure the x-axis if let xAxis = axisSet.xAxis { xAxis.labelingPolicy = .None xAxis.majorIntervalLength = 1 xAxis.axisLineStyle = axisLineStyle var majorTickLocations = Set<nsnumber>() var axisLabels = Set<cptaxislabel>() for (idx, rate) in rates.enumerate() { majorTickLocations.insert(idx) let label = CPTAxisLabel(text: "\(rate.date)", textStyle: CPTTextStyle() label.tickLocation = IDX label.offset = 5.0 label.alignment =.left axislabels.insert (label)} xAxis.majorTickLocations = majorTickLocations xAxis.axisLabels = axisLabels } // 4 - Configure the y-axis if let yAxis = AxisSet. YAxis {yAxis. LabelingPolicy =. FixedInterval yAxis. LabelOffset = 10.0 yAxis. MinorTicksPerInterval = 3 yAxis.majorTickLength = 30 let majorTickLineStyle = CPTMutableLineStyle() majorTickLineStyle.lineColor = Cptcolor.blackcolor ().colorWithAlphacomponent (0.1) yAxis. MajorTickLineStyle = majorTickLineStyle yAxis. MinorTickLength =  20 let minorTickLineStyle = CPTMutableLineStyle() minorTickLineStyle.lineColor = Cptcolor.blackcolor ().colorWithAlphacomponent (0.05) yAxis. MinorTickLineStyle = minorTickLineStyle yAxis. AxisLineStyle = axisLineStyle }</cptaxislabel></nsnumber>Copy the code

In a nutshell, the above code first defines the styles for the axes and headings, then adds the axis Settings for the diagram and configures some attributes for the X and y axes.

Build and run to see the results of these changes.

Functional axis

Better, right? The only drawback is that the axis is too simple to get an accurate representation of the exchange rate from here.

You can fix this so that when a user clicks on a separate bar chart, the app displays the exchange rate represented by that chart. To implement this, we need to add a new attribute:

var priceAnnotation: CPTPlotSpaceAnnotation?
Copy the code

Then add the following code to the barPlot (_ : barWasSelectedAtRecordIndex:) :

// 1 - Is the plot hidden? if plot.hidden == true { return } // 2 - Create style, If necessary let style = CPTMutableTextStyle() style.fontsize = 12.0 style.fontname = "helveticaneue-bold" // 3 - Create  annotation guard let price = numberForPlot(plot, field: UInt(CPTBarPlotField.BarTip.rawValue), recordIndex: idx) as? CGFloat else { return } priceAnnotation? .annotationHostLayer? .removeAnnotation(priceAnnotation) priceAnnotation = CPTPlotSpaceAnnotation(plotSpace: plot.plotSpace! , anchorPlotPoint: [0, 0]) / / 4 - Create number formatter let the formatter = NSNumberFormatter () the formatter. / / 5 - maximumFractionDigits = 2 Create text layer for annotation let priceValue = formatter.stringFromNumber(price)! let textLayer = CPTTextLayer(text: priceValue, style: style) priceAnnotation! .contentLayer = textLayer // 6 - Get plot index var plotIndex: Int = 0 if plot == plot1 { plotIndex = 0 } else if plot == plot2 { plotIndex = 1 } else if plot == plot3 { plotIndex = 2  } // 7 - Get the anchor point for annotation let x = CGFloat(idx) + CGFloat(BarInitialX) + (CGFloat(plotIndex) * CGFloat(BarWidth)) let y = CGFloat(price) + 0.05 priceAnnotation! .anchorPlotPoint = [x, y] // 8 - Add the annotation guard let plotArea = plot.graph? .plotAreaFrame? .plotArea else { return } plotArea.addAnnotation(priceAnnotation)Copy the code

Some explanation is needed here:

  1. Do not show annotations to a hidden bar diagram, and when the diagram has no hidden properties set, you will implement it after incorporating the toggle switch into the diagram.
  2. Also create a text style for your annotations.
  3. Gets the exchange rate for the specified bar chart, and then creates an annotation object if it does not exist.
  4. You need to create one if you don’t have a numeric formatting method, because you need to format it for the exchange rate presentation.
  5. Create a text layer that uses this formatting rate and set the content layer of the annotations to the new text layer.
  6. Gets the bar chart index to place for the annotations you will display.
  7. Calculate the position of the annotation based on the index and set the annotation to use the calculated positionanchorPlotPointThe value of the.
  8. Finally, add annotations to the diagram.

Build and run. Every time you click on a bar in the chart, the value represented by that bar should pop up right above it.

Great! :]

Hide and find

The bar chart looks great, but the toggles at the top of the screen aren’t working, and it’s time to change them.

First, you need to add a help method by adding the following to switch3Changed(_:) :

func hideAnnotation(graph: CPTGraph) { guard let plotArea = graph.plotAreaFrame? .plotArea, priceAnnotation = priceAnnotation else { return } plotArea.removeAnnotation(priceAnnotation) self.priceAnnotation = nil }Copy the code

The code begins by simply removing an if – there annotation.

Next, you want the user to toggle to display a bar chart of exchange rates for a given currency.

To do this, replace the switch1Changed(_:), switch2Changed(_:), and switch3Changed(_:) implementations with the following.

@IBAction func switch1Changed(sender: UISwitch) { let on = sender.on if ! on { hideAnnotation(plot1.graph!) } plot1.hidden = ! on } @IBAction func switch2Changed(sender: UISwitch) { let on = sender.on if ! on { hideAnnotation(plot2.graph!) } plot2.hidden = ! on } @IBAction func switch3Changed(sender: UISwitch) { let on = sender.on if ! on { hideAnnotation(plot3.graph!) } plot3.hidden = ! on }Copy the code

The logic is fairly simple. If the switch is set to off, the associated graph and its visible annotations are hidden, while if set to on, the graph is set to visible.

Build and run. You can now switch between the presentation of each bar chart in the chart. The tutorial has done a good job at this point!

What’s next?

You can download a completed project here.

Wow, that’s interesting! This tutorial highlights the power of Core Plot and hopefully hints at how you can use it in your own apps.

Of course, consult the Core Plot repository for more information, including documentation, examples, and tips.

Also, if you have any questions or comments about this tutorial, feel free to join the discussion forums below.

Have a happy drawing process!