iCharts
The solution for Telegram "March Coding Competition". Completely implemented using Core Animation and Auto Layout (NSLayoutAnchor).
You may take part in beta testing on TestFlight.
Telegram "March Coding Competition" tasks
- Use date from chart_data.json as input for your charts
- Show all 5 charts on one screen
- Implement Day/Night mode
- Add pan gesture on chart in order to highlight points at
xand watch detailed information - Show
datelabels bellowxaxis - Show
valuelabels beforeyaxis - Create
expandable slider controlin order to select visible part of chart and its scale. - Show visible part of [Xi, Xj] in [minY, maxY] segment with vertical insets at top and bottom, where minY = {y | y <= f(x), x in [Xi, Xj]}, maxY = {y | y >= f(x), x in [Xi, Xj]}
- Animate
valuelabels changing - Animate
datelabels changing - Animate appearance/dissappearance of lines on chart
Usage
The simplest case is shown below. You should just create props with arrat of Lines and pass it into render(props:) method.
let chartView = DetailedChartView() // ChartScrollView, PannableChartView, ChartView
// Frame based layout or Auto Layout
let props = ChartView.Props(lines: [
Line(title: "#1", xs: [1, 2, 3], ys: [3, 4, 5], color: .red),
Line(title: "#2", xs: [1, 2, 3], ys: [5, 4, 3], color: .green)
])
chartView.render(props: props)
In order to change theme you should just change Colors property.
chartView.colors = makeColors() // you should write `makeColors` method, it is just example
ChartView.Props properties
lines- an array ofLinestructslineWidth- a positive real value which defines width of line on charthighlithedX- axcoordinate which user highlight onPannableChartViewestimatedGridSpace- estimated space between 2 horizontal lines of gridestimatedXLabelWidth- estimated width of label belowxaxisinset- vertical inset when user renders chart as full-sizedisInFullSize- determines that should we render chart as full-sizedrange- the range of visible part of chart in percents or pointsdidHighlightX- closure which fires when user highlight points onPannableChartView
Colors
It is not necessary to enumerate all properties of Colors struct of each component. You should just know, that you can change color of any part of chart.
See Colors struct in DetailedChartView for more information.
Instalation
TBD
Workspace structure
iChartsDemois an iOS single view application project which demonstrates usage ofiChartsframeworkiChartsis a framework which containsChartViewsource codeUtilsis a static library which contains some useful structs and typealiases such asResult,Variable, etc.
Architecture
TL;DR
- fully implemented on
CALayers - preferred composition over inheritance
- fully data-driven UI
- render only visible part of a chart
Details
The implementation of iCharts framework is highly motivated by Core Animaton CALayers capabilities and classes composition instead of inheritance in order to have flexible, extendable and easy-maintainable code base with SRP principle in the head.
Note: of course in competition situation with time boundaries it is very hard to find trade offs between speed and quality, that's why some principles of SOLID are violated sometime.
Also it should be remarked that all parts of UI are data-driven. Props is used as a dumb representation of UI state at each point of time. This approach makes possible to implement time-traveling debugging feature in future.
ChartView.Props example
extension ChartView {
public struct Props {
public var lines: [Line]
public var lineWidth: CGFloat
public var highlithedX: CGFloat?
public var estimatedGridSpace: Int?
public var estimatedXLabelWidth: Int?
public var inset: CGFloat?
public var isInFullSize: Bool
public var range: Range?
public var didHighlightX: ClosureWith<Output>?
// Init
}
}
In order to implement theming nicely Colors struct is used on each component too.
ChartView.Colors example
extension ChartView {
public struct Colors {
public let labels: UIColor
public let horizontalLines: UIColor
public let lineChart: LineChartLayer.Colors
// Init
public static let initial = Colors(
labels: .gray,
horizontalLines: .gray,
lineChart: .initial)
}
}
Each line of chart is represented by Line struct, where Points is typealias for [CGPoint].
public struct Line {
public let title: String
public var points: Points
public var highlightedPoint: CGPoint?
public let color: UIColor
public var isHidden: Bool
// Init
}
Views & Layers
ChartViewis a core view which is responsible for rendering all chart layers:GridLayerrenders horizontal lines of gridLineChartLayercontainsLineLayers andVerticalLineLayer- LineLayer renders line based on
CGPointvector (ifVerticalLineLayeris also appeared, it will also render circle in order to show highlighted point) VerticalLineLayerrenders vertical line through highlighted points
- LineLayer renders line based on
YLabelsLayerrenders labels above horizontal lines ofGridLayer(yvalues of each line)XLabelsLayerrenders labels belowLinearChartLayerorxaxis in a nutshell (dates in "MMM dd" format)
PannableChartViewis a subclass ofUIControlwhich implements behaviour similar toUIPanGestureRecognizer. It tellsChartViewto show highlighted points and showsChartInfoViewwith details of the points above chart.ChartScrollViewcontains instance ofPannableChartViewandExpandableSliderViewwhich allows user to choose visible part of chart and its scale.DetailedChartViewcontains instance ofChartScrollViewandUITableViewwith names and colors of lines and capability to show/hide them
Normalizer
Normalizeris a protocol which defines method for line normalization based on target rect size of layer.SizeNormalizeris a class which normalize lines based on:- [minY, maxY] segment with
verticalInses(depends onisInFullSizeandverticalInsetproperties) - [0, maxY] segment (full-sized)
- [minY, maxY] segment with
Note about minY, maxY:
- Formal case: minY, maxY are in {y | y in Y1 || Y2 || ... || Yn}, where
||means union (set operation), Yi is a set ofyvalues of theith line - Informal case: minY, maxY are selected among each y of each line in chart
License
iCharts is available under the MIT license. See the LICENSE file for more info.




