Core Plot Pie charts don't show - ios

So I have the following code, followed by the Core plot tutorial by Ray Wenderlich over here but adjusted for my own purposes which looks like this:
class CategoryAnalysis:UIViewController{
var collection:String?
var categories = [Category](){
didSet{
CoreDataHelper.retrieveCategories()
}
}
var categoryTotals:[Double] = []
var colors:[CPTColor] = [CPTColor.red(),CPTColor.blue(),CPTColor.cyan(),CPTColor.orange(),CPTColor.yellow(),CPTColor.darkGray(),CPTColor.green(),CPTColor.purple(),CPTColor.lightGray(),CPTColor.brown(),CPTColor.darkGray()]
#IBOutlet weak var hostView: CPTGraphHostingView!
override func viewDidLoad() {
self.categories = CoreDataHelper.retrieveCategories()
categoryTotals.removeAll()
print (collection)
for category in categories{
categoryTotals.append(ExpensesAdditions().retrieveCategoryAnalysis(collectionName: collection!, category: String(describing: category)))
}
super.viewDidLoad()
print(categoryTotals)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(false)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(false)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
initPlot()
}
func initPlot() {
configureHostView()
configureGraph()
configureChart()
configureLegend()
}
func configureHostView() {
hostView.allowPinchScaling = false
}
func configureGraph() {
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.black()
textStyle.fontName = "HelveticaNeue-Bold"
textStyle.fontSize = 16.0
textStyle.textAlignment = .center
// 3 - Set graph title and text style
graph.title = "Category Analysis"
graph.titleTextStyle = textStyle
graph.titlePlotAreaFrameAnchor = CPTRectAnchor.top
}
func configureChart() {
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.size.height) * 0.7) / 2
pieChart.identifier = NSString(string: graph.title!)
pieChart.startAngle = CGFloat(M_PI_4)
pieChart.sliceDirection = .clockwise
pieChart.labelOffset = -0.6 * pieChart.pieRadius
// 3 - Configure border style
let borderStyle = CPTMutableLineStyle()
borderStyle.lineColor = CPTColor.white()
borderStyle.lineWidth = 2.0
pieChart.borderLineStyle = borderStyle
// 4 - Configure text style
let textStyle = CPTMutableTextStyle()
textStyle.color = CPTColor.white()
textStyle.textAlignment = .center
pieChart.labelTextStyle = textStyle
// 5 - Add chart to graph
graph.add(pieChart)
}
func configureLegend() {
}
}
extension CategoryAnalysis: CPTPieChartDataSource, CPTPieChartDelegate {
func numberOfRecords(for plot: CPTPlot) -> UInt {
return UInt(categories.count)
}
func number(for plot: CPTPlot, field fieldEnum: UInt, record idx: UInt) -> Any? {
if categoryTotals[Int(idx)] == 0{
return 0
}
else {
return categoryTotals[Int(idx)]
}
}
func dataLabel(for plot: CPTPlot, record idx: UInt) -> CPTLayer? {
let value = ExpensesAdditions().convertToMoney(categoryTotals[Int(idx)])
if categoryTotals[Int(idx)] == 0{
let layer2 = CPTTextLayer(text: "")
return layer2
}
else{
let name = String(describing:categories[Int(idx)])
let layer = CPTTextLayer(text: String(format: name, value))
layer.textStyle = plot.labelTextStyle
return layer
}
}
func sliceFill(for pieChart: CPTPieChart, record idx: UInt) -> CPTFill? {
if categoryTotals[Int(idx)]==0{
return CPTFill(color: CPTColor.black())
}
else {
return CPTFill(color: colors[Int(idx)])
}
}
func legendTitle(for pieChart: CPTPieChart, record idx: UInt) -> String? {
return nil
}
}
But when I run this, all I get greeted with, is an empty screen that looks like this instead of a pie chart.
Can someone tell me what is wrong with my code? I'd this something to do with the Swift version as I am currently on Xcode 9

Make sure the hosting view is set up properly. You can inspect hostView in the debugger and make sure it is not nil.
The number(for:field:record:) method signature looks ok, but you need to cast the returned values to NSNumber.
Do you really need to completely rebuild the graph in viewDidLayoutSubviews()? Once the graph is built, Core Plot will take care of layout updates whenever the hosting view bounds change.

Related

iOS Charts not showing all xAxis Value

I am writing an iOS App in Swift 4.2
I am using Charts library to display Horizontal Bar Chart. I need to set its xAxis Values. Only last value is being displayed.
Issue Screenshot:
Code Snippet:
#IBOutlet var chartView: HorizontalBarChartView!
override func viewDidLoad() {
super.viewDidLoad()
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.labelFont = .systemFont(ofSize: 10)
xAxis.drawAxisLineEnabled = false
xAxis.drawGridLinesEnabled = false
xAxis.granularity = 1
xAxis.enabled=true
xAxis.setLabelCount(3, force: false) //Not working as per expectations
xAxis.valueFormatter=IndexAxisValueFormatter(values: ["A","B","C"]) //Not working as per expectations
self.setDataCount(3,values:[142000,122400,100110])
chartView.animate(yAxisDuration: 2.5)
}
func setDataCount(_ count: Int, values:[Double]) {
let barWidth = 2.0
let spaceForBar = 4.0
var n=0
let yVals = (0..<count).map { (i) -> BarChartDataEntry in
let val = values[n]
n+=1
return BarChartDataEntry(x: Double(i)*spaceForBar, y: val)
}
let set1 = BarChartDataSet(entries: yVals, label: "DataSet")
set1.drawIconsEnabled = false
let data = BarChartData(dataSet: set1)
data.setValueFont(UIFont(name:"HelveticaNeue-Light", size:10)!)
data.barWidth = barWidth
chartView.data = data
//let xAxis = chartView.xAxis
//xAxis.setLabelCount(3, force: false)
//xAxis.valueFormatter=IndexAxisValueFormatter(values: ["A","B","C"])
}
I tried to find solutions:
xAxis.valueFormatter=IndexAxisValueFormatter(values: ["A","B","C"])
but these are not working.
This is happening because the default functionality of IndexAxisValueFormatter
You have to code your own custom IAxisValueFormatter like this
final class CustomFormatter: IAxisValueFormatter {
var labels: [String] = []
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
let count = self.labels.count
guard let axis = axis, count > 0 else {
return ""
}
let factor = axis.axisMaximum / Double(count)
let index = Int((value / factor).rounded())
if index >= 0 && index < count {
return self.labels[index]
}
return ""
}
}
Then use it like
let customFormater = CustomFormater()
customFormater.labels = ["A","B","C"]
chartView.xAxis.valueFormatter = customFormater
Make sure the size/count of the data and labels is the same or it wont give you the desired results.
I updated your given code please check changes.
I hope its work for you.
class ViewController: UIViewController {
#IBOutlet var chartView: HorizontalBarChartView!
override func viewDidLoad() {
super.viewDidLoad()
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.labelFont = .systemFont(ofSize: 10)
xAxis.drawAxisLineEnabled = false
xAxis.drawGridLinesEnabled = false
xAxis.granularity = 1
xAxis.enabled=true
xAxis.setLabelCount(3, force: false) //Not working as per expectations
xAxis.valueFormatter = IndexAxisValueFormatter(values: ["A","B","C"])//AxisValueFormatter(values: ["A","B","C"]) //Not working as per expectations
self.setDataCount(3,values:[142000,122400,100110])
chartView.animate(yAxisDuration: 2.5)
}
func setDataCount(_ count: Int, values:[Double]) {
let yVals = (0..<count).map { (i) -> BarChartDataEntry in
let val = values[i]
return BarChartDataEntry(x: Double(i), y: val)
}
let set1 = BarChartDataSet(values: yVals, label: "DataSet")
set1.drawIconsEnabled = false
let data = BarChartData(dataSet: set1)
data.setValueFont(UIFont(name:"HelveticaNeue-Light", size:10)!)
//data.barWidth = barWidth
chartView.data = data
//let xAxis = chartView.xAxis
//xAxis.setLabelCount(3, force: false)
//xAxis.valueFormatter=IndexAxisValueFormatter(values: ["A","B","C"])
}
}

How to make a line graph using CorePlot framework and swift 3?

I can't understand how to make a line plot with CorePlot 2.2 with Swift 3 (Xcode 8, iOS 10).
Can someone explain how to do it?
Particularly, I don't understand how the last function numbers (line 97-103(last lines)) works:
import UIKit
import CorePlot
class dottedLine: UIViewController {
#IBOutlet var hostView: CPTGraphHostingView!
var plot: CPTScatterPlot!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
initPlot()
}
let xValues: [NSNumber] = [1,2,3,4]
let yValues: [NSNumber] = [1,5,4,3]
func initPlot() {
configureHostView()
configureGraph()
configureChart()
configureAxes()
}
func configureHostView() {
hostView.allowPinchScaling = false
}
func configureGraph() {
// 1 - Create the graph
let graph = CPTXYGraph(frame: hostView.bounds)
graph.plotAreaFrame?.masksToBorder = false
hostView.hostedGraph = graph
// 2 - Configure the graph
//graph.apply(CPTTheme(named: CPTThemeName.plainWhiteTheme))
//graph.fill = CPTFill(color: CPTColor.clear())
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.black()
titleStyle.fontName = "HelveticaNeue-Bold"
titleStyle.fontSize = 16.0
titleStyle.textAlignment = .center
graph.titleTextStyle = titleStyle
let title = "Just title"
graph.title = title
graph.titlePlotAreaFrameAnchor = .top
graph.titleDisplacement = CGPoint(x: 0.0, y: -16.0)
// 4 - Set up plot space
let xMin = 0.0
let xMax = 5.0
let yMin = 0.0
let yMax = 15.0
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))
}
func configureChart() {
// 1 - Set up the plot
plot = CPTScatterPlot()
// 2 - Set up style
let plotLineStile = CPTMutableLineStyle()
plotLineStile.lineWidth = 1
plotLineStile.lineColor = CPTColor.black()
plot.dataLineStyle = plotLineStile
// 3- Add plots to graph
guard let graph = hostView.hostedGraph else { return }
plot.dataSource = self
plot.delegate = self
graph.add(plot, to: graph.defaultPlotSpace)
}
func configureAxes() {
}
}
extension dottedLine: CPTScatterPlotDataSource, CPTScatterPlotDelegate {
func numberOfRecords(for plot: CPTPlot) -> UInt {
// number of points
return UInt(xValues.count)
}
func scatterPlot(_ plot: CPTScatterPlot, plotSymbolWasSelectedAtRecord idx: UInt, with event: UIEvent) {
}
/* func numbers(for plot: CPTPlot, field fieldEnum: UInt, recordIndexRange indexRange: NSRange) -> [Any]? {
print("xxxxxxx")
switch CPTScatterPlotField(rawValue: Int(fieldEnum))! {
case .X:
return xValues[index] as NSNumber
case .Y:
return yValues[indexRange] as NSNumber
}
} */
/* func symbols(for plot: CPTScatterPlot, recordIndexRange indexRange: NSRange) -> [CPTPlotSymbol]? {
return xValues
} */
func number(for plot: CPTPlot, field: UInt, record: UInt) -> Any? {
switch CPTScatterPlotField(rawValue: Int(field))! {
case .X:
return 2 as NSNumber
case .Y:
return 3 as NSNumber
}
}
}
For a scatter plot, this method will be called once for the x-value and once for the y-value at each index.
Here is that method from the DatePlot example app:
func number(for plot: CPTPlot, field: UInt, record: UInt) -> Any?
{
switch CPTScatterPlotField(rawValue: Int(field))! {
case .X:
return (oneDay * Double(record)) as NSNumber
case .Y:
return self.plotData[Int(record)] as NSNumber
}
}

Getting EXC_BAD_ACCESS while the object exists

I'm developing a music sequencer with a standard piano roll type UI.
It was working well until I made some changes in the model side but it suddenly started to report EXC_BAD_ACCESS at (seemingly) unrelated part.
What's strange is all the necessary variables have their values properly and actually I can print values with po.
In my understanding, EXC_BAD_ACCESS happens when an object doesn't exist, so this seems quite strange.
My question is:
Is it common to EXC_BAD_ACCESS even the values are there?
If that's the case what is the possible situation to cause that?
Any suggestion is helpful. Thanks
[Below are the codes]
In my subclass of UICollectionViewLayout:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// note cells
let cv = self.collectionView as! YMPianoRollCollectionView;
let pianoRoll = cv.pianoRollViewController;
// Call the below func to get the indexes of the Note Objects included in the specified rect
let indexArray: Array<Int> = pianoRoll!.getNoteIndexes(inRect:rect, useOnlyStartTime: false);
var retArray : [UICollectionViewLayoutAttributes] = []
for i in indexArray {
if let _ = pianoRoll?.pattern.eventSequence[i] as? YMPatternEventNoteOn {
retArray.append( self.layoutAttributesForPatternEventInfo(i) )
}
}
return retArray
}
In my "piano roll" class which contains UICollectionView
func getNoteIndexes(inRect rect:CGRect, useOnlyStartTime: Bool) -> Array<Int> {
//
// Transform given values into musical values
//
let musicRange :YMMusicalValueRange = screenInfo.getMusicalRange(rect);
let startTime = musicRange.origin.time;
let endTime = musicRange.origin.time + musicRange.size.timeLength;
let lowNoteU = musicRange.origin.noteNumber;
let highNoteU = musicRange.origin.noteNumber + musicRange.size.numberOfNotes;
var retArray : [Int] = []
for i in 0..<pattern.eventSequence.count {
if let e = pattern.eventSequence[i] as? YMPatternEventNoteOn {
//
// Prepare ranges
//
let noteNo = e.noteNo; //<- App Crashes Here with BAD_ACCESS
let noteStTime = e.time;
let noteEnTime = e.time + e.duration;
let targetNoteRange = Range<Int>(uncheckedBounds: (lowNoteU, highNoteU));
let targetTimeRange = Range<Int64>(uncheckedBounds: (startTime, endTime))
let noteTimeRange = Range<Int64>(uncheckedBounds: (noteStTime, noteEnTime))
//
// Check the match
//
let noteMatches = targetNoteRange.contains(noteNo);
let timeMatches = useOnlyStartTime ? targetTimeRange.contains(noteStTime)
: targetTimeRange.overlaps(noteTimeRange)
if noteMatches && timeMatches {
retArray.append( i );
NSLog("XXX Found: note \(noteNo) at \(e.time)");
}
}
}
return retArray;
}
Error:- The object states when it crashed
EDIT
Here's the YMPatternEventNoteOn declaration
class YMPatternEvent : Codable, CustomDebugStringConvertible {
var time : YMSequenceTime = 0
// Some utility funcs follow
// ...
}
class YMPatternEventNoteOn : YMPatternEvent {
var noteNo : Int = 64
var velocity : Int = 127
var duration : YMSequenceTime = 480
var tempBendId : Int = 0;
var tempVibratoId : Int = 0;
var tempArpeggioId : Int = 0;
convenience init(time :YMSequenceTime, noteNo : Int, velocity: Int, duration: YMSequenceTime) {
self.init();
self.time = time;
self.noteNo = noteNo;
self.velocity = velocity;
self.duration = duration;
}
// Other methods follow
// ...
}
EDIT2
Note event is created by the user's action
//
// In YMPattern object
//
func insertNote(time:YMSequenceTime, noteNo:Int, velocity:Int, duration:YMSequenceTime) -> Int
{
let onEvent = YMPatternEventNoteOn(time: time, noteNo: noteNo, velocity: velocity, duration: duration);
let retIndex = insertEvent(onEvent);
return retIndex;
}
func insertEvent(_ event: YMPatternEvent) -> Int {
let atTime = event.time;
var retIndex : Int = 0;
if(eventSequence.count<1){
// If it's the first event just add it
eventSequence.append(event);
retIndex = 0;
} else {
// If any event already exists, insert with time order in consideration
var i : Int = 0;
while( atTime > eventSequence[i].time ){
i += 1;
if( i >= eventSequence.count ){
break;
}
}
retIndex = i;
eventSequence.insert(event, at: i)
}
}
//
// In pianoroll view controller
//
func actionButtonReleased(afterDragging: Bool) {
let values:YMMusicalValuePoint = screenInfo.getMusicalPosition(cursorPosition);
// insert new event with default velocity and duration
let _ = pattern.insertNote(time: values.time, noteNo: values.noteNumber, velocity: 127, duration: screenInfo.timeTicsPerDivision());
collectionView.reloadData();
}
I've solved it in a way.
By setting the optimization level to "Whole Module Optimization" it stopped reporting the error.
I don't know what is happening internally but if someone is having the same issue, this might work as a quick fix.

How to format xAxis labels iOS charts

Im implementing a barchart and I've managed to assign the data and labels. However, when i load the barchart, it only shows 3/7 of my labels and I'm not sure why.
the labels show up when i interact with the chart but they go glitchy.
I'm sorry if i haven't explained myself well but i have uploaded a .gif showing my problem.
I really need some help with the formatting of the labels on the xAxis. it would be much appreciated.
Thanks in advance.
gif of problem
i think you have used this library(https://github.com/danielgindi/Charts) ... i have set x-Axis using delegate method of chart
func ChartView()
{
xAxis.drawGridLinesEnabled = false
xAxis.drawLabelsEnabled = true
xAxis.labelPosition = .Bottom
xAxis.axisMinimum = 0.0
xAxis.labelCount = ITEM_COUNT
xAxis.granularity = 1.0
xAxis.valueFormatter = self
self.updateChartData()
}
func updateChartData()
{
self.chartView.data = nil
self.setChartData()
}
func generateLineData() -> LineChartData
{
let d = LineChartData()
let entries = NSMutableArray()
var weightstr = String()
var datestr = String()
entries.addObject(ChartDataEntry(x: Double(index), y: ( Double(dic[setvalue]as! String)!)))
let set = LineChartDataSet(values: entries as? [ChartDataEntry] , label: "X-title")
set.setColor(colorWithHexString("#FE1643"))
set.lineWidth = 2.5
set.setCircleColor( UIColor.whiteColor())
set.circleHoleColor = NSUIColor.greenColor()
set.circleRadius = 5.0
set.circleHoleRadius = 2.5
set.fillColor = UIColor.redColor()
set.mode = .HorizontalBezier
set.valueTextColor = UIColor.lightGrayColor()
set.drawValuesEnabled = true
set.valueFont = UIFont(name: "Exo-Regular", size: FOntSIZE(10.0))!
set.axisDependency = .Left
d.addDataSet(set)
return d
}
func setChartData()
{
let data = CombinedChartData()
data.lineData = self.generateLineData()
self.chartView.xAxis.axisMaximum = Double(months.count)-1
self.chartView.data = data
}
func chartValueSelected(chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight)
{
print("chartValueSelected")
}
func chartValueNothingSelected(chartView: ChartViewBase)
{
print("chartValueNothingSelected")
}
func stringForValue(value: Double, axis: AxisBase?) -> String
{
return months[Int(round(value)) % months.count] as! String
}

Setting Up CorePlot Crosshair in Swift

I am attempting to create a crosshair (vertical line) for my graph in Swift. I have looked over the various Objective-C examples of how to do this, and have mimicked them in the code below:
class viewController: UIViewController {
#IBOutlet weak var graphView: CPTGraphHostingView!
var plot1: CPTScatterPlot!
var plot2: CPTScatterPlot!
var plot3: CPTScatterPlot!
var plotDataSource1: CPTFunctionDataSource?
var plotDataSource2: CPTFunctionDataSource?
var plotDataSource3: CPTFunctionDataSource?
var markerAnnotation: CPTPlotSpaceAnnotation?
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
initPlot()
}
func initPlot() {
configureHostView()
configureGraph()
configureChart()
configureAxes()
}
func configureHostView() {
graphView.allowPinchScaling = true
print("host con called")
}
func configureGraph() {
// 1 - Create the graph
let graph = CPTXYGraph(frame: graphView.bounds)
graph.plotAreaFrame?.masksToBorder = true
graphView.hostedGraph = graph
// 2 - Configure the graph
graph.applyTheme(CPTTheme(named: kCPTPlainWhiteTheme))
graph.fill = CPTFill(color: CPTColor.clearColor())
graph.paddingBottom = 0.0
graph.paddingLeft = 0.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
// 4 - Set up plot space
let xMin = -10.0
let xMax = 10.0
let yMin = -10.0
let yMax = 10.0
guard let plotSpace = graph.defaultPlotSpace as? CPTXYPlotSpace else { return }
plotSpace.allowsUserInteraction = true
plotSpace.xRange = CPTPlotRange(locationDecimal: CPTDecimalFromDouble(xMin), lengthDecimal: CPTDecimalFromDouble(xMax - xMin))
plotSpace.yRange = CPTPlotRange(locationDecimal: CPTDecimalFromDouble(yMin), lengthDecimal: CPTDecimalFromDouble(yMax - yMin))
print("graph con called")
}
func configureChart() {
// 1 - Set up the three plots
plot1 = CPTScatterPlot()
plot2 = CPTScatterPlot()
plot3 = CPTScatterPlot()
// 2 - Set up line style
let lineStyle1 = CPTMutableLineStyle()
lineStyle1.lineColor = CPTColor.blueColor()
lineStyle1.lineWidth = 0.5
let lineStyle2 = CPTMutableLineStyle()
lineStyle2.lineColor = CPTColor.redColor()
lineStyle2.lineWidth = 0.5
let lineStyle3 = CPTMutableLineStyle()
lineStyle3.lineColor = CPTColor.greenColor()
lineStyle3.lineWidth = 0.5
// 3 - Add plots to graph
guard let graph = graphView.hostedGraph else { return }
plot1.delegate = self
plot2.delegate = self
plot3.delegate = self
//let function: CPTDataSourceFunction? = cos
let block1 = {(x: Double) -> Double in
return sin(x)
}
let block2 = {(x: Double) -> Double in
return 1/x
}
let block3 = {(x: Double) -> Double in
return log(x)
}
//if (block != nil) {
plotDataSource1 = CPTFunctionDataSource(forPlot: plot1, withBlock: block1)
plot1.dataSource = plotDataSource1
//}
plotDataSource2 = CPTFunctionDataSource(forPlot: plot2, withBlock: block2)
plot2.dataSource = plotDataSource2
plotDataSource3 = CPTFunctionDataSource(forPlot: plot3, withBlock: block3)
plot3.dataSource = plotDataSource3
plot1.dataLineStyle = lineStyle1
plot2.dataLineStyle = lineStyle2
plot3.dataLineStyle = lineStyle3
graph.addPlot(plot1, toPlotSpace: graph.defaultPlotSpace)
graph.addPlot(plot2, toPlotSpace: graph.defaultPlotSpace)
graph.addPlot(plot3, toPlotSpace: graph.defaultPlotSpace)
print("chart con called")
}
func configureAxes() {
// 1 - Configure styles
let axisLineStyle = CPTMutableLineStyle()
axisLineStyle.lineWidth = 2.0
axisLineStyle.lineColor = CPTColor.blackColor()
let majorGridLineStyle: CPTMutableLineStyle = CPTMutableLineStyle()
majorGridLineStyle.lineWidth = 0.75
majorGridLineStyle.lineColor = CPTColor.grayColor()
let minorGridLineStyle: CPTMutableLineStyle = CPTMutableLineStyle()
minorGridLineStyle.lineWidth = 0.25
minorGridLineStyle.lineColor = CPTColor.whiteColor()
guard let axisSet = graphView.hostedGraph?.axisSet as? CPTXYAxisSet else { return }
// 3 - Configure the x-axis
let axisStyle = CPTMutableTextStyle()
axisStyle.fontSize = 6.0
//
let crosshair = CPTXYAxis()
crosshair.hidden = false
crosshair.coordinate = CPTCoordinate.Y
crosshair.plotSpace = graphView.hostedGraph?.defaultPlotSpace
crosshair.axisConstraints = CPTConstraints(lowerOffset: 10.0)
crosshair.labelingPolicy = CPTAxisLabelingPolicy.None
crosshair.separateLayers = true
crosshair.preferredNumberOfMajorTicks = 6
crosshair.minorTicksPerInterval = 0
let cStyle: CPTMutableLineStyle = CPTMutableLineStyle()
cStyle.lineWidth = 4.0
cStyle.lineColor = CPTColor.orangeColor()
crosshair.axisLineStyle = cStyle
crosshair.majorTickLineStyle = nil
//
let x: CPTXYAxis = axisSet.xAxis!
x.labelingPolicy = .Automatic
x.title = ""
x.labelTextStyle = axisStyle
let y: CPTXYAxis = axisSet.yAxis!
y.labelingPolicy = .Automatic
y.title = ""
y.labelTextStyle = axisStyle
axisSet.axes = [x, y, crosshair]
let hitAnnotationTextStyle: CPTMutableTextStyle = CPTMutableTextStyle()
hitAnnotationTextStyle.color = CPTColor.blackColor()
hitAnnotationTextStyle.fontName = "Helvetica-Bold"
hitAnnotationTextStyle.fontSize = 6
let textLayer: CPTTextLayer = CPTTextLayer(text: "Annotation", style: hitAnnotationTextStyle)
textLayer.cornerRadius = 3.0
textLayer.paddingLeft = 2.0
textLayer.paddingTop = 2.0
textLayer.paddingRight = 2.0
textLayer.paddingBottom = 2.0
textLayer.hidden = false
let graph = CPTXYGraph(frame: graphView.bounds)
let plotSpace = graph.defaultPlotSpace as? CPTXYPlotSpace
let annotation: CPTPlotSpaceAnnotation = CPTPlotSpaceAnnotation(plotSpace: plotSpace!, anchorPlotPoint: [0, 0])
annotation.contentLayer = textLayer
graph.addAnnotation(annotation)
self.markerAnnotation = annotation
print("axes con called")
}
}
extension viewController: CPTPlotSpaceDelegate, CPTPlotDataSource, CPTScatterPlotDelegate {
func numberOfRecordsForPlot(plot: CPTPlot) -> UInt {
print("1")
return (self.plotDataSource1?.dataPlot.cachedDataCount)!
}
func numbersForPlot(plot: CPTPlot, field fieldEnum: UInt, recordIndex index: UInt) -> AnyObject {
print("2")
return (self.plotDataSource1?.dataPlot.cachedDoubleForField(UInt(fieldEnum), recordIndex: UInt(index)))!
}
func plotSpace(space: CPTPlotSpace, willDisplaceBy displacement: CGPoint) -> CGPoint {
print("3")
return CGPointMake(0.0, 0.0)
}
func plotSpace(space: CPTPlotSpace, willChangePlotRangeTo newRange: CPTPlotRange, forCoordinate coordinate: CPTCoordinate) -> CPTPlotRange? {
print("4")
var updatedRange: CPTPlotRange? = nil
let xySpace: CPTXYPlotSpace = (space as! CPTXYPlotSpace)
switch coordinate {
case CPTCoordinate.X:
updatedRange = xySpace.xRange
case CPTCoordinate.Y:
updatedRange = xySpace.yRange
default:
break
}
return updatedRange!
}
func plotSpace(space: CPTPlotSpace, shouldHandlePointingDeviceDownEvent event: UIEvent, atPoint point: CGPoint) -> Bool {
print("5")
let xySpace: CPTXYPlotSpace = (space as! CPTXYPlotSpace)
let graphy = xySpace.graph!
let crosshair = graphy.axisSet!.axes![2] as? CPTXYAxis
var plotPoint = space.plotPointForEvent(event)
let annotation: CPTPlotSpaceAnnotation = self.markerAnnotation!
let textLayer: CPTTextLayer = (annotation.contentLayer as! CPTTextLayer)
var xNumber = plotPoint![CPTCoordinate.X.rawValue]
var yNumber = plotPoint![CPTCoordinate.Y.rawValue]
if xySpace.xRange.containsNumber(xNumber) {
let x: Int = Int(Double(xNumber))
let y: Int = Int(Double(yNumber))
xNumber = x
yNumber = y
let xValue: String = (graphView.hostedGraph!.axisSet?.axes?[0].labelFormatter!.stringForObjectValue(xNumber)!)!
let yValue: String = (graphView.hostedGraph!.axisSet?.axes?[1].labelFormatter!.stringForObjectValue(yNumber)!)!
textLayer.text = "\(xValue), \(yValue)"
textLayer.hidden = false
annotation.anchorPlotPoint = [xNumber, yNumber]
crosshair!.orthogonalPosition = xNumber
crosshair!.hidden = false
} else {
textLayer.hidden = true
crosshair!.hidden = true
}
return false
}
func plotSpace(space: CPTPlotSpace, shouldHandlePointingDeviceDraggedEvent event: UIEvent, atPoint point: CGPoint) -> Bool {
print("6")
return self.plotSpace(space, shouldHandlePointingDeviceDraggedEvent: event, atPoint: point)
}
func plotSpace(space: CPTPlotSpace, shouldHandlePointingDeviceUpEvent event: UIEvent, atPoint point: CGPoint) -> Bool {
print("7")
return false
}
}
The data I am trying to index is created from a CPTFunctionDataSource, so what I am trying to do might be more complicated. Any assistance is appreciated...

Resources