Skip to content
This repository has been archived by the owner on Dec 2, 2020. It is now read-only.

Pan/Zoom and Variable X Axis; many other changes #300

Open
wants to merge 41 commits into
base: feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
59f25dd
Add encoder/decoder for BEMLineGraph properties
mackworth Mar 18, 2017
9bfe179
Add Types to all Arrays
mackworth Mar 18, 2017
7823735
Create new TestBed app to manipulate almost all parameters
mackworth Mar 19, 2017
7dc9f3a
Add colors, gradients, and alphas to TestBed
mackworth Mar 26, 2017
78c8cac
Fix assorted bugs in BEMSimpleLineGraph, especially null-data related
mackworth Mar 26, 2017
a10ad12
Allow use on iPhone and Split View
mackworth Mar 26, 2017
1169854
Fix bug with TouchLineInput color (doesn't change after initial setting)
mackworth Mar 26, 2017
019aa1e
Bug fixes:
mackworth Mar 28, 2017
1c14ccd
Supports bezier curves when line isn't being drawn
mackworth Mar 29, 2017
3ae0ea5
Using cubic instead of quadratic Bezier curves
mackworth Apr 1, 2017
43ff256
Simplifying code for controlPoints in cubicBezier
mackworth Apr 1, 2017
005c92c
Add variable X Axis support
mackworth Apr 5, 2017
5a795c6
Ensure all BEMnulls doesn't crash
mackworth Apr 7, 2017
346fc8b
Remove prev reference lines if axis turned off
mackworth Apr 7, 2017
6faa0f8
Remove prev reference lines if axis turned off
mackworth Apr 7, 2017
78d94cb
Remove prev reference lines if axis turned off
mackworth Apr 7, 2017
73714a6
Implement zoom/pan for data
mackworth Apr 9, 2017
3390172
Add user scaling (zoom/pan) to TestBed UI
mackworth Apr 9, 2017
45e9509
Delegate callback upon scale change
mackworth Apr 11, 2017
8bc4be6
Further implementation of pan/zoom
mackworth Apr 27, 2017
5606474
Better handle overlapping labels with large numbers of points
mackworth Apr 27, 2017
7b3678f
Add Area/Correlation to stats display
mackworth Apr 28, 2017
66cd74b
Major internal restructure
mackworth May 2, 2017
6478f2c
Properties restructure:
mackworth May 2, 2017
064170a
Merge NewBezierAlgo into NoOffsets
mackworth May 2, 2017
d615e0d
Fix cubic merge glitch
mackworth May 2, 2017
bf9d985
Don't add off-screen points to line (fixes animation and faster)
mackworth May 2, 2017
2607d5b
Move to point array versus dual number arrays
mackworth May 3, 2017
a69ef45
Implement xAxis at top Option
mackworth May 3, 2017
13b0172
Drop points off screen, but still include ones immediately offscreen …
mackworth May 6, 2017
fd993c0
Bug fixes:
mackworth May 7, 2017
5c5bcf3
Convert back to NSInteger in API for Swift compatibility
mackworth May 7, 2017
30dfcd8
Misc NSInteger type issues when compiling with strict and floats on 3…
mackworth May 10, 2017
773f5a7
Add ability to take screen shot bigger (or smaller) than screen
mackworth May 11, 2017
d416969
Handle one datapoint in regular routines, not as special case
mackworth May 12, 2017
7a712df
PR #295 fixes
mackworth May 15, 2017
d87e5c0
Update .travis.yml
mackworth May 15, 2017
a4b5155
Bugfixes:
mackworth May 20, 2017
7484033
Merge remote-tracking branch 'origin/variableX' into variableX
mackworth May 20, 2017
d04d190
Add adaptiveDataPoints property that lets calculations be based eithe…
mackworth May 29, 2017
0656b81
Better control over maxZoom
mackworth Jun 6, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ osx_image: xcode8.2
xcode_project: Sample Project/SimpleLineChart.xcodeproj
xcode_scheme: SimpleLineChartTests
xcode_sdk: iphonesimulator
script:
- xcodebuild clean build test -project "Sample Project/SimpleLineChart.xcodeproj" -scheme SimpleLineChartTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 7" ONLY_ACTIVE_ARCH=NO
4 changes: 2 additions & 2 deletions Classes/BEMAverageLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


/// A line displayed horizontally across the graph at the average y-value
@interface BEMAverageLine : NSObject
@interface BEMAverageLine : NSObject <NSCoding>


/// When set to YES, an average line will be displayed on the line graph
Expand All @@ -35,7 +35,7 @@


/// Dash pattern for the average line
@property (strong, nonatomic, nullable) NSArray *dashPattern;
@property (strong, nonatomic, nullable) NSArray <NSNumber *> *dashPattern;


//Label for average line in y axis. Default is blank.
Expand Down
44 changes: 41 additions & 3 deletions Classes/BEMAverageLine.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,60 @@ - (instancetype)init {
self = [super init];
if (self) {
_enableAverageLine = NO;
_color = [UIColor whiteColor];
_alpha = 1.0;
_width = 3.0;
_yValue = NAN;
}

return self;
}
-(void) setLabel:(UILabel *)label {

- (instancetype)initWithCoder:(NSCoder *)coder {

#define RestoreProperty(property, type) {\
if ([coder containsValueForKey:@#property]) { \
self.property = [coder decode ## type ##ForKey:@#property ]; \
}\
}
self = [self init];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullable-to-nonnull-conversion"

RestoreProperty (enableAverageLine, Bool);
RestoreProperty (color, Object);
RestoreProperty (yValue, Float);
RestoreProperty (alpha, Float);
RestoreProperty (width, Float);
RestoreProperty (dashPattern, Object);
RestoreProperty (title, Object);
#pragma clang diagnostic pop

//AverageLine
return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {

#define EncodeProperty(property, type) [coder encode ## type: self.property forKey:@#property]
EncodeProperty (enableAverageLine, Bool);
EncodeProperty (color, Object);
EncodeProperty (yValue, Double);
EncodeProperty (alpha, Double);
EncodeProperty (width, Double);
EncodeProperty (dashPattern, Object);
EncodeProperty (title, Object);
}



- (void)setLabel:(UILabel *)label {
if (_label != label) {
[_label removeFromSuperview];
_label = label;
}
}

-(void) dealloc {
- (void)dealloc {
self.label= nil;
}
@end
2 changes: 1 addition & 1 deletion Classes/BEMCircle.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@
/// The value of the point
@property (nonatomic) CGFloat absoluteValue;

@end
@end
2 changes: 1 addition & 1 deletion Classes/BEMCircle.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ - (void)drawRect:(CGRect)rect {
CGContextFillPath(ctx);
}

@end
@end
58 changes: 29 additions & 29 deletions Classes/BEMGraphCalculator.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,21 @@ - (instancetype)init {
// MARK: -
// MARK: Essential Calculations

- (nonnull NSArray *)calculationDataPointsOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
- (nonnull NSArray <NSNumber *> *)calculationDataPointsOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
NSPredicate *filter = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSNumber *value = (NSNumber *)evaluatedObject;
BOOL retVal = ![value isEqualToNumber:@(BEMNullGraphValue)];
return retVal;
}];
NSArray *filteredArray = [[graph graphValuesForDataPoints] filteredArrayUsingPredicate:filter];
NSArray <NSNumber *> *filteredArray = [[graph graphValuesForDataPoints] filteredArrayUsingPredicate:filter];
return filteredArray;
}

// MARK: -
// MARK: Basic Statistics

- (nonnull NSNumber *)calculatePointValueAverageOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
NSArray *filteredArray = [self calculationDataPointsOnGraph:graph];
NSArray <NSNumber *> *filteredArray = [self calculationDataPointsOnGraph:graph];
if (filteredArray.count == 0) return [NSNumber numberWithInt:0];

NSExpression *expression = [NSExpression expressionForFunction:@"average:" arguments:@[[NSExpression expressionForConstantValue:filteredArray]]];
Expand All @@ -65,7 +65,7 @@ - (nonnull NSNumber *)calculatePointValueAverageOnGraph:(nonnull BEMSimpleLineGr
}

- (nonnull NSNumber *)calculatePointValueSumOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
NSArray *filteredArray = [self calculationDataPointsOnGraph:graph];
NSArray <NSNumber *> *filteredArray = [self calculationDataPointsOnGraph:graph];
if (filteredArray.count == 0) return [NSNumber numberWithInt:0];

NSExpression *expression = [NSExpression expressionForFunction:@"sum:" arguments:@[[NSExpression expressionForConstantValue:filteredArray]]];
Expand All @@ -75,7 +75,7 @@ - (nonnull NSNumber *)calculatePointValueSumOnGraph:(nonnull BEMSimpleLineGraphV
}

- (nonnull NSNumber *)calculatePointValueMedianOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
NSArray *filteredArray = [self calculationDataPointsOnGraph:graph];
NSArray <NSNumber *> *filteredArray = [self calculationDataPointsOnGraph:graph];
if (filteredArray.count == 0) return [NSNumber numberWithInt:0];

NSExpression *expression = [NSExpression expressionForFunction:@"median:" arguments:@[[NSExpression expressionForConstantValue:filteredArray]]];
Expand All @@ -85,19 +85,19 @@ - (nonnull NSNumber *)calculatePointValueMedianOnGraph:(nonnull BEMSimpleLineGra
}

- (nonnull NSNumber *)calculatePointValueModeOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
NSArray *filteredArray = [self calculationDataPointsOnGraph:graph];
NSArray <NSNumber *> *filteredArray = [self calculationDataPointsOnGraph:graph];
if (filteredArray.count == 0) return [NSNumber numberWithInt:0];

NSExpression *expression = [NSExpression expressionForFunction:@"mode:" arguments:@[[NSExpression expressionForConstantValue:filteredArray]]];
NSMutableArray *value = [expression expressionValueWithObject:nil context:nil];
NSNumber *numberValue = [value firstObject];
NSMutableArray <NSNumber *> *values = [expression expressionValueWithObject:nil context:nil];
NSNumber *numberValue = [values firstObject];

if (numberValue) return numberValue;
else return [NSNumber numberWithInt:0];
}

- (nonnull NSNumber *)calculateStandardDeviationOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
NSArray *filteredArray = [self calculationDataPointsOnGraph:graph];
NSArray <NSNumber *> *filteredArray = [self calculationDataPointsOnGraph:graph];
if (filteredArray.count == 0) return [NSNumber numberWithInt:0];

NSExpression *expression = [NSExpression expressionForFunction:@"stddev:" arguments:@[[NSExpression expressionForConstantValue:filteredArray]]];
Expand All @@ -110,7 +110,7 @@ - (nonnull NSNumber *)calculateStandardDeviationOnGraph:(nonnull BEMSimpleLineGr
// MARK: Minimum / Maximum

- (nonnull NSNumber *)calculateMinimumPointValueOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
NSArray *filteredArray = [self calculationDataPointsOnGraph:graph];
NSArray <NSNumber *> *filteredArray = [self calculationDataPointsOnGraph:graph];
if (filteredArray.count == 0) return [NSNumber numberWithInt:0];

NSExpression *expression = [NSExpression expressionForFunction:@"min:" arguments:@[[NSExpression expressionForConstantValue:filteredArray]]];
Expand All @@ -119,7 +119,7 @@ - (nonnull NSNumber *)calculateMinimumPointValueOnGraph:(nonnull BEMSimpleLineGr
}

- (nonnull NSNumber *)calculateMaximumPointValueOnGraph:(nonnull BEMSimpleLineGraphView *)graph {
NSArray *filteredArray = [self calculationDataPointsOnGraph:graph];
NSArray <NSNumber *> *filteredArray = [self calculationDataPointsOnGraph:graph];
if (filteredArray.count == 0) return [NSNumber numberWithInt:0];

NSExpression *expression = [NSExpression expressionForFunction:@"max:" arguments:@[[NSExpression expressionForConstantValue:filteredArray]]];
Expand All @@ -132,18 +132,18 @@ - (nonnull NSNumber *)calculateMaximumPointValueOnGraph:(nonnull BEMSimpleLineGr
// MARK: Integration

- (nonnull NSNumber *)calculateAreaUsingIntegrationMethod:(BEMIntegrationMethod)integrationMethod onGraph:(nonnull BEMSimpleLineGraphView *)graph xAxisScale:(nonnull NSNumber *)scale {
NSArray *fixedDataPoints = [self calculationDataPointsOnGraph:graph];
NSArray <NSNumber *> *fixedDataPoints = [self calculationDataPointsOnGraph:graph];
if (integrationMethod == BEMIntegrationMethodLeftReimannSum) return [self integrateUsingLeftReimannSum:fixedDataPoints xAxisScale:scale];
else if (integrationMethod == BEMIntegrationMethodRightReimannSum) return [self integrateUsingRightReimannSum:fixedDataPoints xAxisScale:scale];
else if (integrationMethod == BEMIntegrationMethodTrapezoidalSum) return [self integrateUsingTrapezoidalSum:fixedDataPoints xAxisScale:scale];
else if (integrationMethod == BEMIntegrationMethodParabolicSimpsonSum) return [self integrateUsingParabolicSimpsonSum:fixedDataPoints xAxisScale:scale];
else return [NSNumber numberWithInt:0];
}

- (NSNumber *)integrateUsingLeftReimannSum:(nonnull NSArray *)graphPoints xAxisScale:(nonnull NSNumber *)scale {
- (NSNumber *)integrateUsingLeftReimannSum:(nonnull NSArray <NSNumber *> *)graphPoints xAxisScale:(nonnull NSNumber *)scale {
NSNumber *totalArea = [NSNumber numberWithInt:0];

NSMutableArray *leftSumPoints = graphPoints.mutableCopy;
NSMutableArray <NSNumber *> *leftSumPoints = graphPoints.mutableCopy;
[leftSumPoints removeLastObject];

for (NSNumber *yValue in leftSumPoints) {
Expand All @@ -154,10 +154,10 @@ - (NSNumber *)integrateUsingLeftReimannSum:(nonnull NSArray *)graphPoints xAxisS
return totalArea;
}

- (NSNumber *)integrateUsingRightReimannSum:(nonnull NSArray *)graphPoints xAxisScale:(nonnull NSNumber *)scale {
- (NSNumber *)integrateUsingRightReimannSum:(nonnull NSArray <NSNumber *> *)graphPoints xAxisScale:(nonnull NSNumber *)scale {
NSNumber *totalArea = [NSNumber numberWithInt:0];

NSMutableArray *rightSumPoints = graphPoints.mutableCopy;
NSMutableArray <NSNumber *> *rightSumPoints = graphPoints.mutableCopy;
[rightSumPoints removeObjectAtIndex:0];

for (NSNumber *yValue in rightSumPoints) {
Expand All @@ -168,16 +168,16 @@ - (NSNumber *)integrateUsingRightReimannSum:(nonnull NSArray *)graphPoints xAxis
return totalArea;
}

- (NSNumber *)integrateUsingTrapezoidalSum:(nonnull NSArray *)graphPoints xAxisScale:(nonnull NSNumber *)scale {
- (NSNumber *)integrateUsingTrapezoidalSum:(nonnull NSArray <NSNumber *> *)graphPoints xAxisScale:(nonnull NSNumber *)scale {
NSNumber *left = [self integrateUsingLeftReimannSum:graphPoints xAxisScale:scale];
NSNumber *right = [self integrateUsingRightReimannSum:graphPoints xAxisScale:scale];
NSNumber *trapezoidal = [NSNumber numberWithFloat:(left.floatValue+right.floatValue)/2];
return trapezoidal;
}

- (NSNumber *)integrateUsingParabolicSimpsonSum:(nonnull NSArray *)points xAxisScale:(nonnull NSNumber *)scale {
- (NSNumber *)integrateUsingParabolicSimpsonSum:(nonnull NSArray <NSNumber *> *)points xAxisScale:(nonnull NSNumber *)scale {
// Get all the points from the graph into a mutable array
NSMutableArray *graphPoints = points.mutableCopy;
NSMutableArray <NSNumber *> *graphPoints = points.mutableCopy;

// If there are two or fewer points on the graph, no parabolic curve can be created. Thus, the next most accurate method will be employed: a trapezoidal summation
if (graphPoints.count <= 2) return [self integrateUsingTrapezoidalSum:points xAxisScale:scale];
Expand Down Expand Up @@ -233,27 +233,27 @@ - (NSNumber *)integrateUsingParabolicSimpsonSum:(nonnull NSArray *)points xAxisS
- (NSNumber *)calculateCorrelationCoefficientUsingCorrelationMethod:(BEMCorrelationMethod)correlationMethod onGraph:(BEMSimpleLineGraphView *)graph xAxisScale:(nonnull NSNumber *)scale {
// Grab the x and y points
// Because a BEMSimpleLineGraph object simply increments X-Values, we must calculate the values here
NSArray *yPoints = [self calculationDataPointsOnGraph:graph];
NSMutableArray *xPoints = [NSMutableArray arrayWithCapacity:yPoints.count];
NSArray <NSNumber *> *yPoints = [self calculationDataPointsOnGraph:graph];
NSMutableArray <NSNumber *> *xPoints = [NSMutableArray arrayWithCapacity:yPoints.count];
if (scale == nil || scale.floatValue == 0.0) {
for (NSUInteger i = 1; i <= yPoints.count; i++) {
[xPoints addObject:[NSNumber numberWithInteger:i]];
[xPoints addObject:@(i)];
}
} else {
for (NSUInteger i = 1; i <= yPoints.count; i++) {
[xPoints addObject:[NSNumber numberWithFloat:(i*scale.floatValue)]];
[xPoints addObject:@(i*scale.floatValue)];
}
}

// Set the initial values of our sum counts
NSInteger pointsCount = yPoints.count;
NSUInteger pointsCount = yPoints.count;
CGFloat sumY = 0.0;
CGFloat sumX = 0.0;
CGFloat sumXY = 0.0;
CGFloat sumX2 = 0.0;
CGFloat sumY2 = 0.0;

NSInteger iterationCount = 0;
NSUInteger iterationCount = 0;
for (NSNumber *yPoint in yPoints) {
NSNumber *xPoint = xPoints[iterationCount];
iterationCount++;
Expand All @@ -272,13 +272,13 @@ - (NSNumber *)calculateCorrelationCoefficientUsingCorrelationMethod:(BEMCorrelat
// Calculate the correlational value
CGFloat numeratorFirstChunk = (pointsCount * sumXY); // Calculate the mean of the points
CGFloat numeratorSecondChunk = (sumX * sumY); // Calculate total graph values
CGFloat denomenatorFirstChunk = sqrt(pointsCount * sumX2 - (sumX * sumX)); // Square root of the sum of all X-Values squared
CGFloat denomenatorSecondChunk = sqrt(pointsCount * sumY2 - (sumY * sumY)); // Square root of the sum of all Y-Values squared
CGFloat correlation = (numeratorFirstChunk - numeratorSecondChunk) / (denomenatorFirstChunk * denomenatorSecondChunk);
double denomenatorFirstChunk = sqrt(pointsCount * sumX2 - (sumX * sumX)); // Square root of the sum of all X-Values squared
double denomenatorSecondChunk = sqrt(pointsCount * sumY2 - (sumY * sumY)); // Square root of the sum of all Y-Values squared
double correlation = (numeratorFirstChunk - numeratorSecondChunk) / (denomenatorFirstChunk * denomenatorSecondChunk);

// NSLog(@"CORRELATION:\nSlope: %f\nIntercept:%f\nCorrelation:%f", slope, intercept, correlation);

return [NSNumber numberWithFloat:correlation];
return @(correlation);
}

- (BEMPearsonCorrelationStrength)calculatePearsonCorrelationStrengthOnGraph:(BEMSimpleLineGraphView *)graph xAxisScale:(nonnull NSNumber *)scale {
Expand Down
24 changes: 9 additions & 15 deletions Classes/BEMLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,14 @@ typedef NS_ENUM(NSUInteger, BEMLineGradientDirection) {

//----- POINTS -----//

/// All of the Y-axis values for the points
@property (strong, nonatomic, nonnull) NSArray *arrayOfPoints;
/// All of the values for the points
@property (strong, nonatomic, nonnull) NSArray <NSValue *> *points;

/// All of the X-Axis coordinates used to draw vertical lines through
@property (strong, nonatomic, nonnull) NSArray *arrayOfVerticalReferenceLinePoints;

/// The value used to offset the fringe vertical reference lines when the x-axis labels are on the edge
@property (assign, nonatomic) CGFloat verticalReferenceHorizontalFringeNegation;
@property (strong, nonatomic, nonnull) NSArray <NSNumber *> *arrayOfVerticalReferenceLinePoints;

/// All of the Y-Axis coordinates used to draw horizontal lines through
@property (strong, nonatomic, nullable) NSArray *arrayOfHorizontalReferenceLinePoints;

/// All of the point values
@property (strong, nonatomic, nullable) NSArray *arrayOfValues;
@property (strong, nonatomic, nullable) NSArray <NSNumber *> *arrayOfHorizontalReferenceLinePoints;

/** Draw thin, translucent, reference lines using the provided X-Axis and Y-Axis coordinates.
@see Use \p arrayOfVerticalReferenceLinePoints to specify vertical reference lines' positions. Use \p arrayOfHorizontalReferenceLinePoints to specify horizontal reference lines' positions. */
Expand All @@ -77,10 +71,10 @@ typedef NS_ENUM(NSUInteger, BEMLineGradientDirection) {
@property (assign, nonatomic) BOOL enableTopReferenceFrameLine;

/** Dash pattern for the references line on the X axis */
@property (nonatomic, strong, nullable) NSArray *lineDashPatternForReferenceXAxisLines;
@property (nonatomic, strong, nullable) NSArray <NSNumber *> *lineDashPatternForReferenceXAxisLines;

/** Dash pattern for the references line on the Y axis */
@property (nonatomic, strong, nullable) NSArray *lineDashPatternForReferenceYAxisLines;
@property (nonatomic, strong, nullable) NSArray <NSNumber *> *lineDashPatternForReferenceYAxisLines;

/** If a null value is present, interpolation would draw a best fit line through the null point bound by its surrounding points. Default: YES */
@property (assign, nonatomic) BOOL interpolateNullValues;
Expand All @@ -99,16 +93,16 @@ typedef NS_ENUM(NSUInteger, BEMLineGradientDirection) {
@property (strong, nonatomic, nullable) UIColor *topColor;

/// A color gradient applied to the area above the line, inside of its superview. If set, it will be drawn on top of the fill from the \p topColor property.
@property (assign, nonatomic, nullable) CGGradientRef topGradient;
@property (strong, nonatomic, nullable) __attribute__((NSObject)) CGGradientRef topGradient;

/// The color of the area below the line, inside of its superview
@property (strong, nonatomic, nullable) UIColor *bottomColor;

/// A color gradient applied to the area below the line, inside of its superview. If set, it will be drawn on top of the fill from the \p bottomColor property.
@property (assign, nonatomic, nullable) CGGradientRef bottomGradient;
@property (strong, nonatomic, nullable) __attribute__((NSObject)) CGGradientRef bottomGradient;

/// A color gradient to be applied to the line. If this property is set, it will mask (override) the \p color property.
@property (assign, nonatomic, nullable) CGGradientRef lineGradient;
@property (strong, nonatomic, nullable) __attribute__((NSObject)) CGGradientRef lineGradient;

/// The drawing direction of the line gradient color
@property (nonatomic) BEMLineGradientDirection lineGradientDirection;
Expand Down
Loading