@@ -129,6 +129,16 @@ - (instancetype) initWithFrame:(CGRect)frame {
129129- (instancetype ) initWithCoder : (NSCoder *)coder {
130130 self = [super initWithCoder: coder];
131131 if (self) [self commonInit ];
132+ [self restorePropertyWithCoder: coder];
133+ return self;
134+ }
135+
136+ -(void ) decodeRestorableStateWithCoder : (NSCoder *)coder {
137+ [super decodeRestorableStateWithCoder: coder];
138+ [self restorePropertyWithCoder: coder];
139+ }
140+
141+ -(void ) restorePropertyWithCoder : (NSCoder *) coder {
132142
133143#define RestoreProperty (property, type ) \
134144if ([coder containsValueForKey: @#property]) { \
@@ -179,23 +189,26 @@ - (instancetype) initWithCoder:(NSCoder *)coder {
179189 RestoreProperty (formatStringForValues, Object);
180190
181191 RestoreProperty (averageLine, Object);
182- return self;
183192#pragma clang diagnostic pop
184193}
185194
186- - (void ) encodeWithEncoder : (NSCoder *)coder {
195+ -(void ) encodeRestorableStateWithCoder : (NSCoder *)coder {
196+ [super encodeRestorableStateWithCoder: coder];
197+ [self encodePropertiesWithCoder: coder];
198+ }
187199
188- #define EncodeProperty (property, type ) [coder encode ## type: self .property forKey: @#property]
200+ - (void ) encodeWithCoder : (NSCoder *)coder {
201+ [super encodeWithCoder: coder];
202+ [self encodePropertiesWithCoder: coder];
203+ }
189204
205+ -(void ) encodePropertiesWithCoder : (NSCoder *) coder {
190206
191- [ super encodeWithCoder: coder];
207+ # define EncodeProperty ( property, type ) [coder encode ## type: self .property forKey: @#property]
192208
193209 EncodeProperty (labelFont, Object);
194210 EncodeProperty (animationGraphEntranceTime, Float);
195211 EncodeProperty (animationGraphStyle, Integer);
196- EncodeProperty (enableReferenceAxisFrame, Bool);
197- EncodeProperty (enableTopReferenceAxisFrameLine, Bool);
198- EncodeProperty (enableRightReferenceAxisFrameLine, Bool);
199212
200213 EncodeProperty (colorXaxisLabel, Object);
201214 EncodeProperty (colorYaxisLabel, Object);
@@ -383,7 +396,7 @@ - (void)layoutNumberOfPoints {
383396 }
384397 self.noDataLabel .text = noDataText ?: NSLocalizedString(@" No Data" , nil );
385398 self.noDataLabel .font = self.noDataLabelFont ?: [UIFont preferredFontForTextStyle: UIFontTextStyleCaption1];
386- self.noDataLabel .textColor = self.noDataLabelColor ?: (self.colorLine ?: [UIColor blackColor ]);
399+ self.noDataLabel .textColor = self.noDataLabelColor ?: (self.colorXaxisLabel ?: [UIColor blackColor ]);
387400
388401 [self .viewForFirstBaselineLayout addSubview: self .noDataLabel];
389402
@@ -522,16 +535,20 @@ -(BEMCircle *) circleDotAtIndex:(NSUInteger) index forValue:(CGFloat) dotValue r
522535
523536 [yAxisValues addObject: @(positionOnYAxis)];
524537
538+ BEMCircle *circleDot = nil ;
539+ if (reuseNumber < self.circleDots .count ) {
540+ circleDot = self.circleDots [reuseNumber];
541+ }
525542 if (dotValue >= BEMNullGraphValue) {
526543 // If we're dealing with an null value, don't draw the dot (but put it in yAxis to interpolate line)
544+ [circleDot removeFromSuperview ];
527545 return nil ;
528546 }
529547
530- BEMCircle *circleDot;
531548 CGRect dotFrame = CGRectMake (0 , 0 , self.sizePoint , self.sizePoint );
532- if (reuseNumber < self.circleDots .count ) {
533- circleDot = self.circleDots [reuseNumber];
549+ if (circleDot) {
534550 circleDot.frame = dotFrame;
551+ [circleDot setNeedsDisplay ];
535552 } else {
536553 circleDot = [[BEMCircle alloc ] initWithFrame: dotFrame];
537554 [self .circleDots addObject: circleDot];
@@ -573,34 +590,37 @@ - (void)drawDots {
573590
574591 BEMCircle * circleDot = [self circleDotAtIndex: index forValue: dotValue reuseNumber: index];
575592 UILabel * label = nil ;
593+ if (index < self.permanentPopups .count ) {
594+ label = self.permanentPopups [index];
595+ } else {
596+ label = [[UILabel alloc ] initWithFrame: CGRectZero];
597+ [self .permanentPopups addObject: label ];
598+ }
599+
576600 if (circleDot) {
577601 [self addSubview: circleDot];
578602
579- if (self.alwaysDisplayPopUpLabels == YES ) {
580- if (![self .delegate respondsToSelector: @selector (lineGraph:alwaysDisplayPopUpAtIndex: )] ||
581- [self .delegate lineGraph: self alwaysDisplayPopUpAtIndex: index]) {
582- if (index < self.permanentPopups .count ) {
583- label = self.permanentPopups [index];
584- } else {
585- label = [[UILabel alloc ] initWithFrame: CGRectZero];
586- [self .permanentPopups addObject: label ];
587- }
588- label = [self configureLabel: label forPoint: circleDot ];
589-
590- [self adjustXLocForLabel: label avoidingDot: circleDot.frame];
591-
592- UILabel * leftNeighbor = (index >= 1 && self.permanentPopups [index-1 ].superview ) ? self.permanentPopups [index-1 ] : nil ;
593- UILabel * secondNeighbor = (index >= 2 && self.permanentPopups [index-2 ].superview ) ? self.permanentPopups [index-2 ] : nil ;
594- BOOL showLabel = [self adjustYLocForLabel: label
595- avoidingDot: circleDot.frame
596- andNeighbors: leftNeighbor.frame
597- and: secondNeighbor.frame ];
598- if (showLabel) {
599- [self addSubview: label];
600- } else {
601- [label removeFromSuperview ];
602- }
603+ if ((self.alwaysDisplayPopUpLabels == YES ) &&
604+ (![self .delegate respondsToSelector: @selector (lineGraph:alwaysDisplayPopUpAtIndex: )] ||
605+ [self .delegate lineGraph: self alwaysDisplayPopUpAtIndex: index])) {
606+ label = [self configureLabel: label forPoint: circleDot ];
607+
608+ [self adjustXLocForLabel: label avoidingDot: circleDot.frame];
609+
610+ UILabel * leftNeighbor = (index >= 1 && self.permanentPopups [index-1 ].superview ) ? self.permanentPopups [index-1 ] : nil ;
611+ UILabel * secondNeighbor = (index >= 2 && self.permanentPopups [index-2 ].superview ) ? self.permanentPopups [index-2 ] : nil ;
612+ BOOL showLabel = [self adjustYLocForLabel: label
613+ avoidingDot: circleDot.frame
614+ andNeighbors: leftNeighbor.frame
615+ and: secondNeighbor.frame ];
616+ if (showLabel) {
617+ [self addSubview: label];
618+ } else {
619+ [label removeFromSuperview ];
603620 }
621+ } else {
622+ // not showing labels this time, so remove if any
623+ [label removeFromSuperview ];
604624 }
605625
606626 // Dot and/or label entrance animation
@@ -628,6 +648,8 @@ - (void)drawDots {
628648 } completion: nil ];
629649 }
630650
651+ } else {
652+ [label removeFromSuperview ];
631653 }
632654 }
633655 for (NSUInteger i = self.circleDots .count -1 ; i>=numberOfPoints; i--) {
@@ -679,6 +701,8 @@ - (void)drawLine {
679701 line.verticalReferenceHorizontalFringeNegation = xAxisHorizontalFringeNegationValue;
680702 line.arrayOfVerticalReferenceLinePoints = self.enableReferenceXAxisLines ? xAxisLabelPoints : nil ;
681703 line.arrayOfHorizontalReferenceLinePoints = self.enableReferenceYAxisLines ? yAxisLabelPoints : nil ;
704+ } else {
705+ line.enableReferenceLines = NO ;
682706 }
683707
684708 line.color = self.colorLine ;
@@ -726,8 +750,13 @@ - (void)drawXAxis {
726750 }
727751 [self addSubview: self .backgroundXAxis];
728752
729- self.backgroundXAxis .backgroundColor = self.colorBackgroundXaxis ?: self.colorBottom ;
730- self.backgroundXAxis .alpha = self.alphaBackgroundXaxis ;
753+ if (self.colorBackgroundXaxis ) {
754+ self.backgroundXAxis .backgroundColor = self.colorBackgroundXaxis ;
755+ self.backgroundXAxis .alpha = self.alphaBackgroundXaxis ;
756+ } else {
757+ self.backgroundXAxis .backgroundColor = self.colorBottom ;
758+ self.backgroundXAxis .alpha = self.alphaBottom ;
759+ }
731760
732761 NSArray <NSNumber *> *axisIndices = nil ;
733762 if ([self .delegate respondsToSelector: @selector (incrementPositionsForXAxisOnLineGraph: )]) {
@@ -751,6 +780,7 @@ - (void)drawXAxis {
751780 baseIndex = increment - 1 - offset;
752781 }
753782 }
783+ if (increment == 0 ) increment = 1 ;
754784 NSMutableArray <NSNumber *> *values = [NSMutableArray array ];
755785 NSUInteger index = baseIndex;
756786 while (index < numberOfPoints) {
@@ -933,7 +963,7 @@ - (void)drawYAxis {
933963 self.frame .size .width - self.YAxisLabelXOffset - 1 .0f :
934964 0.0 ),
935965 0 ,
936- self.YAxisLabelXOffset - 1 . 0f ,
966+ self.YAxisLabelXOffset ,
937967 self.frame .size .height );
938968
939969 if (!self.backgroundYAxis ) {
@@ -942,8 +972,13 @@ - (void)drawYAxis {
942972 self.backgroundYAxis .frame = frameForBackgroundYAxis;
943973 }
944974 [self addSubview: self .backgroundYAxis];
945- self.backgroundYAxis .backgroundColor = self.colorBackgroundYaxis ?: self.colorTop ;
946- self.backgroundYAxis .alpha = self.alphaBackgroundYaxis ;
975+ if (self.colorBackgroundYaxis ) {
976+ self.backgroundYAxis .backgroundColor = self.colorBackgroundYaxis ;
977+ self.backgroundYAxis .alpha = self.alphaBackgroundYaxis ;
978+ } else {
979+ self.backgroundYAxis .backgroundColor = self.colorTop ;
980+ self.backgroundYAxis .alpha = self.alphaTop ;
981+ }
947982
948983 [yAxisLabelPoints removeAllObjects ];
949984
@@ -1114,14 +1149,13 @@ - (UILabel *)configureLabel: (UILabel *) oldLabel forPoint: (BEMCircle *)circleD
11141149 NSNumber *value = (index <= dataPoints.count ) ? value = dataPoints[index] : @(0 ); // @((NSInteger) circleDot.absoluteValue)
11151150#pragma clang diagnostic push
11161151#pragma clang diagnostic ignored "-Wformat-nonliteral"
1152+ // note this can indeed crash if delegate provides junk for formatString (e.g. %@); try/catch doesn't work
11171153 NSString *formattedValue = [NSString stringWithFormat: self .formatStringForValues, value.doubleValue];
11181154#pragma clang diagnostic pop
11191155 newPopUpLabel.text = [NSString stringWithFormat: @" %@%@%@ " , prefix, formattedValue, suffix];
11201156 }
1121- NSLog (@" %@ before SizeToFit: %@ " ,newPopUpLabel.text , NSStringFromCGRect(newPopUpLabel.frame ));
11221157 CGSize requiredSize = [newPopUpLabel sizeThatFits: CGSizeMake (100 .0f , CGFLOAT_MAX)];
11231158 newPopUpLabel.frame = CGRectMake (10 , 10 , requiredSize.width +10 .0f , requiredSize.height +10 .0f );
1124- NSLog (@" %@ after SizeToFit: %@ " ,newPopUpLabel.text , NSStringFromCGRect(newPopUpLabel.frame ));
11251159 return newPopUpLabel;
11261160}
11271161
0 commit comments