-
-
Save ivnsch/f6e285eb0c86bb831510 to your computer and use it in GitHub Desktop.
// NOTE: you may have to set the module in the storyboard to "SwiftCharts", otherwise the view may not be recognized correctly, which leads to axis, labels and guidelines not showing | |
class HelloWorld: UIViewController { | |
private var chart: Chart? // arc | |
@IBOutlet weak var chartView: ChartBaseView! | |
private var didLayout: Bool = false | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil) | |
} | |
override func viewDidLayoutSubviews() { | |
super.viewDidLayoutSubviews() | |
if !self.didLayout { | |
self.didLayout = true | |
self.initChart() | |
} | |
} | |
private func initChart() { | |
// map model data to chart points | |
let chartPoints: [ChartPoint] = [(2, 2), (4, 4), (6, 6), (8, 10), (12, 14)].map{ChartPoint(x: ChartAxisValueInt($0.0), y: ChartAxisValueInt($0.1))} | |
let labelSettings = ChartLabelSettings(font: ExamplesDefaults.labelFont) | |
// define x and y axis values (quick-demo way, see other examples for generation based on chartpoints) | |
let xValues = stride(from: 0, through: 16, by: 2).map {ChartAxisValueInt($0, labelSettings: labelSettings)} | |
let yValues = stride(from: 0, through: 16, by: 2).map {ChartAxisValueInt($0, labelSettings: labelSettings)} | |
// create axis models with axis values and axis title | |
let xModel = ChartAxisModel(axisValues: xValues, axisTitleLabel: ChartAxisLabel(text: "Axis title", settings: labelSettings)) | |
let yModel = ChartAxisModel(axisValues: yValues, axisTitleLabel: ChartAxisLabel(text: "Axis title", settings: labelSettings.defaultVertical())) | |
let chartFrame = self.chartView.frame | |
// generate axes layers and calculate chart inner frame, based on the axis models | |
let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis(chartSettings: ExamplesDefaults.chartSettings, chartFrame: chartFrame, xModel: xModel, yModel: yModel) | |
let (xAxis, yAxis, innerFrame) = (coordsSpace.xAxis, coordsSpace.yAxis, coordsSpace.chartInnerFrame) | |
// create layer with guidelines | |
let guidelinesLayerSettings = ChartGuideLinesDottedLayerSettings(linesColor: UIColor.black, linesWidth: ExamplesDefaults.guidelinesWidth) | |
let guidelinesLayer = ChartGuideLinesDottedLayer(xAxis: xAxis, yAxis: yAxis, innerFrame: innerFrame, settings: guidelinesLayerSettings) | |
// view generator - this is a function that creates a view for each chartpoint | |
let viewGenerator = {(chartPointModel: ChartPointLayerModel, layer: ChartPointsViewsLayer, chart: Chart) -> UIView? in | |
let viewSize: CGFloat = Env.iPad ? 30 : 20 | |
let center = chartPointModel.screenLoc | |
let label = UILabel(frame: CGRect(x: center.x - viewSize / 2, y: center.y - viewSize / 2, width: viewSize, height: viewSize)) | |
label.backgroundColor = UIColor.green | |
label.textAlignment = NSTextAlignment.center | |
label.text = "\(chartPointModel.chartPoint.y.description)" | |
label.font = ExamplesDefaults.labelFont | |
return label | |
} | |
// create layer that uses viewGenerator to display chartpoints | |
let chartPointsLayer = ChartPointsViewsLayer(xAxis: xAxis, yAxis: yAxis, innerFrame: innerFrame, chartPoints: chartPoints, viewGenerator: viewGenerator) | |
// create chart instance with frame and layers | |
let chart = Chart( | |
view: self.chartView!, | |
layers: [ | |
coordsSpace.xAxis, | |
coordsSpace.yAxis, | |
guidelinesLayer, | |
chartPointsLayer | |
] | |
) | |
self.chart = chart | |
} | |
func rotated() { | |
for view in self.chartView.subviews { | |
view.removeFromSuperview() | |
} | |
self.initChart() | |
} | |
} |
I'm using the swift2.0 branch (Swift 2.0 doesn't require Array() anymore).
About the stretched image, this happens on rotation change, because the code didn't handle it. Added the handling, should be fixed now.
Genius! That's amazing. Now rotation works perfectly 👍
I'm sorry, I don't like using betas so I didn't know about swift2.0 and the change in Array(stride:) definition.
How can I quote your library in my App?
Hey there - I'm using this sample code in my app and if I call initChart after the view is rendered (after getting some data from a server) only the curve layer is displayed (the axis are not) - any idea of what I'm doing wrong?
here is how you can repro the issue using latest sample code:
- add a UIView to the iPhone storyboard in DetailView Controller/View
-> call view chartView and make it an outlet to the Detail class - update (aka hack) DetailViewController.swift as follow (mainly using the sample code from above)
//
// DetailViewController.swift
// SwiftCharts
//
// Created by ischuetz on 20/04/15.
// Copyright (c) 2015 ivanschuetz. All rights reserved.
//
import UIKit
import SwiftCharts
class DetailViewController: UIViewController, UISplitViewControllerDelegate {
@IBOutlet weak var detailDescriptionLabel: UILabel!
@IBOutlet weak var chartView: ChartBaseView!
// lazy var chartFrame: CGRect! = {
// CGRectMake(0, 80, self.view.frame.size.width, self.view.frame.size.height - 80)
// }()
var detailItem: Example? {
didSet {
self.configureView()
//initChart()
}
}
override func viewDidLoad() {
super.viewDidLoad()
var timer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "initChart", userInfo: nil, repeats: false)
}
func initChart() {
// map model data to chart points
let chartPoints: [ChartPoint] = [(2, 2), (4, 4), (6, 6), (8, 10), (12, 14)].map{ChartPoint(x: ChartAxisValueInt($0.0), y: ChartAxisValueInt($0.1))}
let labelSettings = ChartLabelSettings(font: ExamplesDefaults.labelFont)
// define x and y axis values (quick-demo way, see other examples for generation based on chartpoints)
let xValues = 0.stride( through: 16, by: 2).map {ChartAxisValueInt($0, labelSettings: labelSettings)}
let yValues = 0.stride( through: 16, by: 2).map {ChartAxisValueInt($0, labelSettings: labelSettings)}
// create axis models with axis values and axis title
let xModel = ChartAxisModel(axisValues: xValues, axisTitleLabel: ChartAxisLabel(text: "Axis title", settings: labelSettings))
let yModel = ChartAxisModel(axisValues: yValues, axisTitleLabel: ChartAxisLabel(text: "Axis title", settings: labelSettings.defaultVertical()))
let chartFrame = self.chartView.frame
// generate axes layers and calculate chart inner frame, based on the axis models
let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis(chartSettings: ExamplesDefaults.chartSettings, chartFrame: chartFrame, xModel: xModel, yModel: yModel)
let (xAxis, yAxis, innerFrame) = (coordsSpace.xAxis, coordsSpace.yAxis, coordsSpace.chartInnerFrame)
// create layer with guidelines
let guidelinesLayerSettings = ChartGuideLinesDottedLayerSettings(linesColor: UIColor.blackColor(), linesWidth: ExamplesDefaults.guidelinesWidth)
let guidelinesLayer = ChartGuideLinesDottedLayer(xAxis: xAxis, yAxis: yAxis, innerFrame: innerFrame, settings: guidelinesLayerSettings)
// view generator - this is a function that creates a view for each chartpoint
let viewGenerator = {(chartPointModel: ChartPointLayerModel, layer: ChartPointsViewsLayer, chart: Chart) -> UIView? in
let viewSize: CGFloat = Env.iPad ? 30 : 20
let center = chartPointModel.screenLoc
let label = UILabel(frame: CGRectMake(center.x - viewSize / 2, center.y - viewSize / 2, viewSize, viewSize))
label.backgroundColor = UIColor.greenColor()
label.textAlignment = NSTextAlignment.Center
label.text = "\(chartPointModel.chartPoint.y)"
label.font = ExamplesDefaults.labelFont
return label
}
// create layer that uses viewGenerator to display chartpoints
let chartPointsLayer = ChartPointsViewsLayer(xAxis: xAxis, yAxis: yAxis, innerFrame: innerFrame, chartPoints: chartPoints, viewGenerator: viewGenerator)
// create chart instance with frame and layers
let chart = Chart(
view: self.chartView!,
layers: [
coordsSpace.xAxis,
coordsSpace.yAxis,
guidelinesLayer,
chartPointsLayer
]
)
self.chartView.setNeedsDisplay()
//self.chart = chart
}
var currentExampleController: UIViewController?
func configureView() {
if let example: Example = self.detailItem {
switch example {
case .HelloWorld:
self.setSplitSwipeEnabled(true)
self.showExampleController(HelloWorld())
case .Bars:
self.setSplitSwipeEnabled(true)
self.showExampleController(BarsExample())
case .StackedBars:
self.setSplitSwipeEnabled(true)
self.showExampleController(StackedBarsExample())
case .BarsPlusMinus:
self.setSplitSwipeEnabled(true)
self.showExampleController(BarsPlusMinusWithGradientExample())
case .GroupedBars:
self.setSplitSwipeEnabled(true)
self.showExampleController(GroupedBarsExample())
case .BarsStackedGrouped:
self.setSplitSwipeEnabled(true)
self.showExampleController(GroupedAndStackedBarsExample())
case .Scatter:
self.setSplitSwipeEnabled(true)
self.showExampleController(ScatterExample())
case .Notifications:
self.setSplitSwipeEnabled(true)
self.showExampleController(NotificationsExample())
case .Target:
self.setSplitSwipeEnabled(true)
self.showExampleController(TargetExample())
case .Areas:
self.setSplitSwipeEnabled(true)
self.showExampleController(AreasExample())
case .Bubble:
self.setSplitSwipeEnabled(true)
self.showExampleController(BubbleExample())
case .Combination:
self.setSplitSwipeEnabled(true)
self.showExampleController(BarsPlusMinusAndLinesExample())
case .Scroll:
self.setSplitSwipeEnabled(false)
self.automaticallyAdjustsScrollViewInsets = false
self.showExampleController(ScrollExample())
case .Coords:
self.setSplitSwipeEnabled(true)
self.showExampleController(CoordsExample())
case .Tracker:
self.setSplitSwipeEnabled(false)
self.showExampleController(TrackerExample())
case .EqualSpacing:
self.setSplitSwipeEnabled(true)
self.showExampleController(EqualSpacingExample())
case .CustomUnits:
self.setSplitSwipeEnabled(true)
self.showExampleController(CustomUnitsExample())
case .Multival:
self.setSplitSwipeEnabled(true)
self.showExampleController(MultipleLabelsExample())
case .MultiAxis:
self.setSplitSwipeEnabled(true)
self.showExampleController(MultipleAxesExample())
case .MultiAxisInteractive:
self.setSplitSwipeEnabled(true)
self.showExampleController(MultipleAxesInteractiveExample())
case .CandleStick:
self.setSplitSwipeEnabled(true)
self.showExampleController(CandleStickExample())
case .Cubiclines:
self.setSplitSwipeEnabled(true)
self.showExampleController(CubicLinesExample())
case .NotNumeric:
self.setSplitSwipeEnabled(true)
self.showExampleController(NotNumericExample())
case .CandleStickInteractive:
self.setSplitSwipeEnabled(false)
self.showExampleController(CandleStickInteractiveExample())
case .Trendline:
self.setSplitSwipeEnabled(true)
self.showExampleController(TrendlineExample())
}
}
}
private func showExampleController(controller: UIViewController) {
if let currentExampleController = self.currentExampleController {
currentExampleController.removeFromParentViewController()
currentExampleController.view.removeFromSuperview()
}
self.addChildViewController(controller)
//self.view.addSubview(controller.view)
self.currentExampleController = controller
}
private func setSplitSwipeEnabled(enabled: Bool) {
if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad {
let splitViewController = UIApplication.sharedApplication().delegate?.window!!.rootViewController as! UISplitViewController
splitViewController.presentsWithGesture = enabled
}
}
}
results: click on any example, details view is shown - results: after 2 sec the graph is shown but the axis layers are not shown... self.chartView.setNeedsDisplay seems to have no effect - Any idea of what I'm missing? Thanks!
Hi! How can I add this: "@IBOutlet weak var chartView: ChartBaseView!" ? I not see ChartBaseView when i drag UIView to the class and I can't convert my UIView to ChartBaseView. Can somebody please help me? Thanks!
Hi, I tried to rewrite UIView to ChartBaseView to IBOutlet and I have the same problem as reivax (axis are missing). Did you resolve this? Thank you!
The image is completely stretched! The proportions are not kept!