diff --git a/Classes/Drawing/BarDrawingLayer.swift b/Classes/Drawing/BarDrawingLayer.swift index 8b9b74d..1705a43 100644 --- a/Classes/Drawing/BarDrawingLayer.swift +++ b/Classes/Drawing/BarDrawingLayer.swift @@ -8,6 +8,9 @@ internal class BarDrawingLayer: ScrollableGraphViewDrawingLayer { private var barWidth: CGFloat = 4 private var shouldRoundCorners = false + override init(layer: Any) { + super.init(layer: layer) + } init(frame: CGRect, barWidth: CGFloat, barColor: UIColor, barLineWidth: CGFloat, barLineColor: UIColor, shouldRoundCorners: Bool) { super.init(viewportWidth: frame.size.width, viewportHeight: frame.size.height) diff --git a/Classes/Drawing/DotDrawingLayer.swift b/Classes/Drawing/DotDrawingLayer.swift index 9f2f4a0..15ecd6b 100644 --- a/Classes/Drawing/DotDrawingLayer.swift +++ b/Classes/Drawing/DotDrawingLayer.swift @@ -9,6 +9,10 @@ internal class DotDrawingLayer: ScrollableGraphViewDrawingLayer { private var customDataPointPath: ((_ centre: CGPoint) -> UIBezierPath)? + override init(layer: Any) { + super.init(layer: layer) + } + init(frame: CGRect, fillColor: UIColor, dataPointType: ScrollableGraphViewDataPointType, dataPointSize: CGFloat, customDataPointPath: ((_ centre: CGPoint) -> UIBezierPath)? = nil) { self.dataPointType = dataPointType diff --git a/Classes/Drawing/FillDrawingLayer.swift b/Classes/Drawing/FillDrawingLayer.swift index 97b3c29..04b3ae7 100644 --- a/Classes/Drawing/FillDrawingLayer.swift +++ b/Classes/Drawing/FillDrawingLayer.swift @@ -5,8 +5,11 @@ internal class FillDrawingLayer : ScrollableGraphViewDrawingLayer { // Fills are only used with lineplots and we need // to know what the line looks like. - private var lineDrawingLayer: LineDrawingLayer + private var lineDrawingLayer: LineDrawingLayer! + override init(layer: Any) { + super.init(layer: layer) + } init(frame: CGRect, fillColor: UIColor, lineDrawingLayer: LineDrawingLayer) { self.lineDrawingLayer = lineDrawingLayer diff --git a/Classes/Drawing/GradientDrawingLayer.swift b/Classes/Drawing/GradientDrawingLayer.swift index 319fa5c..ff77d91 100644 --- a/Classes/Drawing/GradientDrawingLayer.swift +++ b/Classes/Drawing/GradientDrawingLayer.swift @@ -9,7 +9,7 @@ internal class GradientDrawingLayer : ScrollableGraphViewDrawingLayer { // Gradient fills are only used with lineplots and we need // to know what the line looks like. - private var lineDrawingLayer: LineDrawingLayer + private var lineDrawingLayer: LineDrawingLayer! lazy private var gradientMask: CAShapeLayer = ({ let mask = CAShapeLayer() @@ -34,6 +34,12 @@ internal class GradientDrawingLayer : ScrollableGraphViewDrawingLayer { addMaskLayer() self.setNeedsDisplay() } + override init(layer: Any) { + self.startColor = UIColor.black + self.endColor = UIColor.black + self.gradientType = .linear + super.init(layer: layer) + } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") diff --git a/Classes/Drawing/LineDrawingLayer.swift b/Classes/Drawing/LineDrawingLayer.swift index 373a3cb..9798df0 100644 --- a/Classes/Drawing/LineDrawingLayer.swift +++ b/Classes/Drawing/LineDrawingLayer.swift @@ -30,7 +30,13 @@ internal class LineDrawingLayer : ScrollableGraphViewDrawingLayer { required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override init(layer: Any) { + // Default values + lineStyle = .smooth + shouldFill = false + lineCurviness = 1.0 + super.init(layer: layer) + } internal func createLinePath() -> UIBezierPath { guard let owner = owner else { diff --git a/Classes/Drawing/ReferenceLineDrawingView.swift b/Classes/Drawing/ReferenceLineDrawingView.swift index 827ebad..7dbfa26 100644 --- a/Classes/Drawing/ReferenceLineDrawingView.swift +++ b/Classes/Drawing/ReferenceLineDrawingView.swift @@ -93,9 +93,9 @@ internal class ReferenceLineDrawingView : UIView { switch(settings.positionType) { case .relative: - createReferenceLines(in: initialRect, atRelativePositions: self.settings.relativePositions, forPath: referenceLinePath) + createReferenceLines(in: initialRect, relativeLines: self.settings.relativeLines, forPath: referenceLinePath) case .absolute: - createReferenceLines(in: initialRect, atAbsolutePositions: self.settings.absolutePositions, forPath: referenceLinePath) + createReferenceLines(in: initialRect, absoluteLines: self.settings.absoluteLines, forPath: referenceLinePath) } return referenceLinePath @@ -110,54 +110,61 @@ internal class ReferenceLineDrawingView : UIView { return numberFormatter } - private func createReferenceLines(in rect: CGRect, atRelativePositions relativePositions: [Double], forPath path: UIBezierPath) { + private func createReferenceLines(in rect: CGRect, relativeLines: [ReferenceLine], forPath path: UIBezierPath) { let height = rect.size.height - var relativePositions = relativePositions + var relativeLines = relativeLines // If we are including the min and max already need to make sure we don't redraw them. if(self.settings.includeMinMax) { - relativePositions = relativePositions.filter({ (x:Double) -> Bool in - return (x != 0 && x != 1) + relativeLines = relativeLines.filter({ (x: ReferenceLine) -> Bool in + return (x.position != 0 && x.position != 1) }) } - for relativePosition in relativePositions { + for relativeLine in relativeLines { - let yPosition = height * CGFloat(1 - relativePosition) + let yPosition = height * CGFloat(1 - relativeLine.position) let lineStart = CGPoint(x: 0, y: rect.origin.y + yPosition) let lineEnd = CGPoint(x: lineStart.x + lineWidth, y: lineStart.y) - createReferenceLineFrom(from: lineStart, to: lineEnd, in: path) + createReferenceLineFrom(from: lineStart, to: lineEnd, in: path, withLabel: relativeLine.label) } } - private func createReferenceLines(in rect: CGRect, atAbsolutePositions absolutePositions: [Double], forPath path: UIBezierPath) { + private func createReferenceLines(in rect: CGRect, absoluteLines: [ReferenceLine], forPath path: UIBezierPath) { - for absolutePosition in absolutePositions { + for absoluteLine in absoluteLines { - let yPosition = calculateYPositionForYAxisValue(value: absolutePosition) + let yPosition = calculateYPositionForYAxisValue(value: absoluteLine.position) - // don't need to add rect.origin.y to yPosition like we do for relativePositions, + // don't need to add rect.origin.y to yPosition like we do for relativeLines, // as we calculate the position for the y axis value in the previous line, // this already takes into account margins, etc. let lineStart = CGPoint(x: 0, y: yPosition) let lineEnd = CGPoint(x: lineStart.x + lineWidth, y: lineStart.y) - createReferenceLineFrom(from: lineStart, to: lineEnd, in: path) + createReferenceLineFrom(from: lineStart, to: lineEnd, in: path, withLabel: absoluteLine.label) } } - private func createReferenceLineFrom(from lineStart: CGPoint, to lineEnd: CGPoint, in path: UIBezierPath) { + private func createReferenceLineFrom(from lineStart: CGPoint, to lineEnd: CGPoint, in path: UIBezierPath, withLabel label: String?) { if(self.settings.shouldAddLabelsToIntermediateReferenceLines) { let value = calculateYAxisValue(for: lineStart) let numberFormatter = referenceNumberFormatter() - var valueString = numberFormatter.string(from: value as NSNumber)! - if(self.settings.shouldAddUnitsToIntermediateReferenceLineLabels) { - valueString += " \(units)" + var valueString: String + + if let label = label { + valueString = label + } else { + valueString = numberFormatter.string(from: value as NSNumber)! + + if(self.settings.shouldAddUnitsToIntermediateReferenceLineLabels) { + valueString += " \(units)" + } } addLine(withTag: valueString, from: lineStart, to: lineEnd, in: path) diff --git a/Classes/Drawing/ScrollableGraphViewDrawingLayer.swift b/Classes/Drawing/ScrollableGraphViewDrawingLayer.swift index 864e346..82e16c5 100644 --- a/Classes/Drawing/ScrollableGraphViewDrawingLayer.swift +++ b/Classes/Drawing/ScrollableGraphViewDrawingLayer.swift @@ -27,6 +27,9 @@ internal class ScrollableGraphViewDrawingLayer : CAShapeLayer { setup() } + override init(layer: Any) { + super.init() + } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") diff --git a/Classes/Plots/Plot.swift b/Classes/Plots/Plot.swift index 580bbe8..7b34420 100644 --- a/Classes/Plots/Plot.swift +++ b/Classes/Plots/Plot.swift @@ -103,7 +103,7 @@ open class Plot { } private func dequeue(animation: GraphPointAnimation) { - if let index = currentAnimations.index(of: animation) { + if let index = currentAnimations.firstIndex(of: animation) { currentAnimations.remove(at: index) } diff --git a/Classes/Reference/LabelPool.swift b/Classes/Reference/LabelPool.swift index 9dde79c..de07ac9 100644 --- a/Classes/Reference/LabelPool.swift +++ b/Classes/Reference/LabelPool.swift @@ -29,7 +29,7 @@ internal class LabelPool { else { label = UILabel() labels.append(label) - let newLabelIndex = labels.index(of: label)! + let newLabelIndex = labels.firstIndex(of: label)! relations[pointIndex] = newLabelIndex } diff --git a/Classes/Reference/ReferenceLines.swift b/Classes/Reference/ReferenceLines.swift index 38f12aa..bf24dd6 100644 --- a/Classes/Reference/ReferenceLines.swift +++ b/Classes/Reference/ReferenceLines.swift @@ -26,9 +26,17 @@ open class ReferenceLines { open var referenceLinePosition = ScrollableGraphViewReferenceLinePosition.left @IBInspectable open var positionType = ReferenceLinePositioningType.relative - @IBInspectable open var relativePositions: [Double] = [0.25, 0.5, 0.75] - @IBInspectable open var absolutePositions: [Double] = [25, 50, 75] - @IBInspectable open var includeMinMax: Bool = true + + open var relativeLines: [ReferenceLine] = [ReferenceLine(position: 0, label: "start"), + ReferenceLine(position: 0.25, label: "a"), + ReferenceLine(position: 0.5, label: "b"), + ReferenceLine(position: 0.75, label: "c"), + ReferenceLine(position: 1, label: "end")] + open var absoluteLines: [ReferenceLine] = [ReferenceLine(position: 25), + ReferenceLine(position: 50), + ReferenceLine(position: 75)] + + @IBInspectable open var includeMinMax: Bool = false /// Whether or not to add labels to the intermediate reference lines. @IBInspectable open var shouldAddLabelsToIntermediateReferenceLines: Bool = true @@ -72,7 +80,14 @@ open class ReferenceLines { // Need this for external frameworks. } } - +open class ReferenceLine { + public let position: Double + public let label: String? + public init(position: Double, label: String? = nil) { + self.position = position + self.label = label + } +} @objc public enum ScrollableGraphViewReferenceLinePosition : Int { case left diff --git a/Classes/ScrollableGraphView.swift b/Classes/ScrollableGraphView.swift index 9dc5d18..56e4064 100644 --- a/Classes/ScrollableGraphView.swift +++ b/Classes/ScrollableGraphView.swift @@ -981,7 +981,7 @@ fileprivate class SGVQueue { // We have to be our own data source for interface builder. #if TARGET_INTERFACE_BUILDER -public extension ScrollableGraphView : ScrollableGraphViewDataSource { +extension ScrollableGraphView : ScrollableGraphViewDataSource { var numberOfDisplayItems: Int { get { diff --git a/GraphView/GraphView.xcodeproj/project.pbxproj b/GraphView/GraphView.xcodeproj/project.pbxproj index e2372b3..ac94ede 100644 --- a/GraphView/GraphView.xcodeproj/project.pbxproj +++ b/GraphView/GraphView.xcodeproj/project.pbxproj @@ -287,13 +287,16 @@ TargetAttributes = { 2918399D1C72E6A400753A45 = { CreatedOnToolsVersion = 7.2.1; - LastSwiftMigration = 1000; + LastSwiftMigration = 1130; + }; + E10847832129DC60009A9586 = { + LastSwiftMigration = 1130; }; }; }; buildConfigurationList = 291839991C72E6A400753A45 /* Build configuration list for PBXProject "GraphView" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -512,7 +515,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.ios.GraphViewCode; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -529,7 +532,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.ios.GraphViewCode; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -546,7 +549,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.ios.GraphViewIB; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -563,7 +567,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.ios.GraphViewIB; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; diff --git a/GraphView/GraphViewCode/Examples.swift b/GraphView/GraphViewCode/Examples.swift index aacf13b..4e97c50 100644 --- a/GraphView/GraphViewCode/Examples.swift +++ b/GraphView/GraphViewCode/Examples.swift @@ -141,7 +141,12 @@ class Examples : ScrollableGraphViewDataSource { referenceLines.referenceLineLabelFont = UIFont.boldSystemFont(ofSize: 8) referenceLines.referenceLineColor = UIColor.white.withAlphaComponent(0.2) referenceLines.referenceLineLabelColor = UIColor.white - referenceLines.relativePositions = [0, 0.2, 0.4, 0.6, 0.8, 1] + referenceLines.relativeLines = [ReferenceLine(position: 0), + ReferenceLine(position: 0.2), + ReferenceLine(position: 0.4), + ReferenceLine(position: 0.6), + ReferenceLine(position: 0.8), + ReferenceLine(position: 1)] referenceLines.dataPointLabelColor = UIColor.white.withAlphaComponent(1) @@ -257,7 +262,10 @@ class Examples : ScrollableGraphViewDataSource { referenceLines.positionType = .absolute // Reference lines will be shown at these values on the y-axis. - referenceLines.absolutePositions = [10, 20, 25, 30] + referenceLines.absoluteLines = [ReferenceLine(position: 10), + ReferenceLine(position: 20), + ReferenceLine(position: 25), + ReferenceLine(position: 30)] referenceLines.includeMinMax = false referenceLines.dataPointLabelColor = UIColor.white.withAlphaComponent(0.5) diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..d622024 --- /dev/null +++ b/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version:5.0 +// +import PackageDescription + +let package = Package(name: "ScrollableGraphView", + platforms: [.iOS(.v8)], + products: [.library(name: "ScrollableGraphView", + targets: ["ScrollableGraphView"])], + targets: [.target(name: "ScrollableGraphView", + path: "Classes")], + swiftLanguageVersions: [.v5]) diff --git a/README.md b/README.md index dfe2dba..3ec1574 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,10 @@ referenceLines.referenceLineLabelColor = UIColor.white referenceLines.positionType = .absolute // Reference lines will be shown at these values on the y-axis. -referenceLines.absolutePositions = [10, 20, 25, 30] +referenceLines.absoluteLines = [ReferenceLine(position: 10), + ReferenceLine(position: 20), + ReferenceLine(position: 25), + ReferenceLine(position: 30)] referenceLines.includeMinMax = false referenceLines.dataPointLabelColor = UIColor.white.withAlphaComponent(0.5) @@ -554,7 +557,12 @@ let referenceLines = ReferenceLines() referenceLines.referenceLineLabelFont = UIFont.boldSystemFont(ofSize: 8) referenceLines.referenceLineColor = UIColor.white.withAlphaComponent(0.2) referenceLines.referenceLineLabelColor = UIColor.white -referenceLines.relativePositions = [0, 0.2, 0.4, 0.6, 0.8, 1] +referenceLines.relativeLines = [ReferenceLine(position: 0), + ReferenceLine(position: 0.2), + ReferenceLine(position: 0.4), + ReferenceLine(position: 0.6), + ReferenceLine(position: 0.8), + ReferenceLine(position: 1)] referenceLines.dataPointLabelColor = UIColor.white.withAlphaComponent(1)