Reputation: 2237
My bar graph disappears when I switch my app to background and then again comes back to foreground.
It's like shown below :
||| || ||
So in the above picture I have gaps, that means when my app is in background core plot does not draw bar graph. Is it a limitation of core plot?
My main task is to draw one bar per second and I have done this, but it's not working while in background. Is there some other alternate option by which I can achieve this?
Here is what I tried:
I made my graph object nil and then tried it reloading when app again comes back to foreground. But it didn't work.
-(void)redrawGraphWhenApplicationEntersForeground
{
NSLog(@"reload graph");
NSLog(@"all plots : %@ , %@", [self.graph allPlots], plotArray);
DDLogInfo(@"relaod graph when entered in Foreground ");
// [self.data removeAllObjects];
//Create graph and set it as host view's graph
self.graph = nil;
[self.graph reloadDataIfNeeded];
}`
Here is my full code :
// Update is called by a timer ( of 10 second) , so that each second this method will be called and it will draw a bar.
- (void)update:(id)data1 withState:(NSInteger) type
{
switch (type) {
case ZAP_UPDATE:
if(curLinkType == DOWNLINK)
{
[self drawDownlinkGrpah];
}else if(curLinkType == UPLINK)
{
[self drawUplinkGrpah];
}
[gauge setValue:speedValue];
break;
case ZAP_DONE:
[self displayDone:type speedBps:speedBps pktLoss:pktLoss srcdst:[zap destinationAddress]];
onTap = false;
runningTime=0;
if(gauge != nil){
[gauge setValue:0];
}
{
NSArray *parameter = [NSArray arrayWithObjects: speed, unit, nil];
[self performSelector:@selector(stopGauge:) withObject:parameter afterDelay:0.2];
}
}
}
- (void)drawDownlinkGrpah {
DownlinCount++;
self.downlinkdata = [NSMutableArray array];
double position = DownlinCount*((4*10)/(double)durationval);
NSDictionary *bar = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:position],BAR_POSITION,
[NSNumber numberWithDouble:speedBarValue],BAR_HEIGHT,
[UIColor orangeColor],COLOR,
nil];
[self.downlinkdata addObject:bar];
self.data = self.downlinkdata;
[self generateBarPlotForDownlink:YES];
}
- (void)drawUplinkGrpah {
UplinkCount++;
self.uplinkdata = [NSMutableArray array];
double position = UplinkCount*((4*10)/(double)durationval);
NSDictionary *bar = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:position],BAR_POSITION,
[NSNumber numberWithDouble:speedBarValue],BAR_HEIGHT,
[UIColor orangeColor],COLOR,
nil];
[self.uplinkdata addObject:bar];
self.data = self.uplinkdata;
[self generateBarPlotForDownlink:NO];
}
- (NSInteger)getBarposition:(NSInteger)samplesize {
return (4*10)/samplesize;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)resetGraph:(UIImageView*) imageview {
for(UIView *view in imageview.subviews)
[view removeFromSuperview];
[imageview setImage:[UIImage imageNamed:@"graph_container"]];
}
#pragma mark -
-(void)appGoesinBackground
{
// NSLog(@"make nil graph");
// DDLogInfo(@"remove graph when entered in background ");
//
self.graph = nil;
// [self.data removeAllObjects];
[plotArray removeAllObjects]; // remove all data before entering to background
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(redrawGraphWhenApplicationEntersForeground)
name: UIApplicationDidBecomeActiveNotification
object: nil];
}
// redraw graph ..
-(void)redrawGraphWhenApplicationEntersForeground
{
NSLog(@"reload graph");
NSLog(@"all plots : %@ , %@", [self.graph allPlots], plotArray);
DDLogInfo(@"relaod graph when entered in Foreground ");
// [self.data removeAllObjects];
//Create graph and set it as host view's graph
// self.graph = nil;
//
for (CPTBarPlot *p in plotArray) {
// [self.graph addPlot:p];
[p reloadData];
}
}
#pragma mark - generate bar plot
- (void)generateBarPlotForDownlink:(BOOL)enabled
{
NSLog(@"generateBarPlotForDownlink >>>>>>");
//Create host view
self.hostingView = [[CPTGraphHostingView alloc] initWithFrame:CGRectMake(-35, -20, 128, 73)];
//Create graph and set it as host view's graph
self.graph = [[CPTXYGraph alloc] initWithFrame:self.downlinkImageView.frame];
self.graph.plotAreaFrame.masksToBorder = NO;
[self.hostingView setHostedGraph:self.graph];
if(enabled) // for downlink graph ..
{
self.downlinkImageView.image=nil;
[self.downlinkImageView addSubview:self.hostingView];
}
else{ // for uplink graph ..
self.uplinkImageView.image=nil;
[self.uplinkImageView addSubview:self.hostingView];
}
// Create bar plot and add it to the graph
CPTBarPlot *plot = [[CPTBarPlot alloc] init] ;
plot.dataSource = self;
plot.delegate = self;
//set axes ranges
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:
CPTDecimalFromFloat(AXIS_START)
length:CPTDecimalFromFloat((AXIS_END - AXIS_START)+1)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:
CPTDecimalFromFloat(AXIS_START)
length:CPTDecimalFromFloat(maxYRange)];
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;
axisSet.xAxis.majorIntervalLength = CPTDecimalFromFloat(1.0f);
axisSet.yAxis.majorIntervalLength = CPTDecimalFromFloat(1.0f);
axisSet.xAxis.minorTickLength = 1.0f;
axisSet.yAxis.minorTickLength = 1.0f;
axisSet.hidden=YES;
axisSet.xAxis.labelingPolicy=CPTAxisLabelingPolicyNone;
axisSet.yAxis.labelingPolicy=CPTAxisLabelingPolicyNone;
float barwidht = (2*10.0)/(float)durationval;
NSString *inStr = [NSString stringWithFormat: @"%f", barwidht];
plot.barWidth = [[NSDecimalNumber decimalNumberWithString:inStr] // Need to change according sample // 1.5 for 10 , 0.75 for 20
decimalValue];
plot.barOffset = [[NSDecimalNumber decimalNumberWithString:@"5.0"]
decimalValue];
plot.barCornerRadius = 0.0;
// Remove bar outlines
CPTMutableLineStyle *borderLineStyle = [CPTMutableLineStyle lineStyle];
borderLineStyle.lineColor = [CPTColor clearColor];
plot.lineStyle = borderLineStyle;
plot.identifier = @"chocoplot";
[self.graph addPlot:plot];
// Add plot to array in case if app is moved to background state ..
[plotArray addObject:plot];
NSLog(@"plot : %@",plot);
NSLog(@"plot added ..%lu", (unsigned long)plotArray.count );
}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
if ( [plot.identifier isEqual:@"chocoplot"] )
return [self.data count];
return 0;
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
if ( [plot.identifier isEqual:@"chocoplot"] )
{
NSDictionary *bar = [self.data objectAtIndex:index];
if(fieldEnum == CPTBarPlotFieldBarLocation)
return [bar valueForKey:BAR_POSITION];
else if(fieldEnum ==CPTBarPlotFieldBarTip)
return [bar valueForKey:BAR_HEIGHT];
}
return [NSNumber numberWithFloat:0];
}
-(CPTFill *)barFillForBarPlot:(CPTBarPlot *)barPlot
recordIndex:(NSUInteger)index
{
if ( [barPlot.identifier isEqual:@"chocoplot"] )
{
NSDictionary *bar = [self.data objectAtIndex:index];
CPTGradient *gradient = [CPTGradient gradientWithBeginningColor:[CPTColor redColor]
endingColor:[bar valueForKey:@"COLOR"]
beginningPosition:0.0 endingPosition:0.6 ];
[gradient setGradientType:CPTGradientTypeAxial];
[gradient setAngle:320.0];
CPTFill *fill = [CPTFill fillWithGradient:gradient];
return fill;
}
return [CPTFill fillWithColor:[CPTColor colorWithComponentRed:1.0 green:1.0 blue:1.0 alpha:1.0]];
}
Screenshot:
Upvotes: 2
Views: 122
Reputation: 2237
Here is the code that worked for me :
- (void)drawDownlinkGrpah {
NSLog(@"drawDownlinkGrpah CAlled");
DownlinCount++;
double position = DownlinCount*((4*10)/(double)durationval);
NSDictionary *bar = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:position],BAR_POSITION,
[NSNumber numberWithDouble:speedBarValue],BAR_HEIGHT,
[UIColor orangeColor],COLOR,
nil];
[self.downlinkdata addObject:bar];
self.data = self.downlinkdata;
[self generateBarPlotForDownlink:YES];
}
#pragma mark - generate bar
- (void)generateBarPlotForDownlink:(BOOL)enabled
{
if(enabled)
{
self.downlinkImageView.image=nil;
if(![self.hostingView isDescendantOfView:self.downlinkImageView])
{
// Configure hosting view so that it appears from fresh ..
[self configureGraph];
[self.downlinkImageView addSubview:self.hostingView];
NSLog(@"hosting view added in downlink view ");
}
}
else
{
self.uplinkImageView.image=nil;
// if hosting view is not in uplink view
if(![self.hostingView isDescendantOfView:self.uplinkImageView])
{
// Configure hosting view so that it appears from fresh ..
[self configureGraph];
[self.uplinkImageView addSubview:self.hostingView];
NSLog(@"hosting view added in uplink view ");
}
}
//set axes ranges
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:
CPTDecimalFromFloat(AXIS_START)
length:CPTDecimalFromFloat((AXIS_END - AXIS_START)+1)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:
CPTDecimalFromFloat(AXIS_START)
length:CPTDecimalFromFloat(maxYRange)];
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;
axisSet.xAxis.majorIntervalLength = CPTDecimalFromFloat(1.0f);
axisSet.yAxis.majorIntervalLength = CPTDecimalFromFloat(1.0f);
axisSet.xAxis.minorTickLength = 1.0f;
axisSet.yAxis.minorTickLength = 1.0f;
axisSet.hidden=YES;
axisSet.xAxis.labelingPolicy=CPTAxisLabelingPolicyNone;
axisSet.yAxis.labelingPolicy=CPTAxisLabelingPolicyNone;
// Create bar plot and add it to the graph
NSLog(@"plot created %ld", (long)durationval);
CPTBarPlot *plot = [[CPTBarPlot alloc] init] ;
plot.dataSource = self;
plot.delegate = self;
float barwidht = (2*10.0)/(float)durationval;
NSString *inStr = [NSString stringWithFormat: @"%f", barwidht]; //CPTDecimalFromDouble(2.0);
plot.barWidth = [[NSDecimalNumber decimalNumberWithString:inStr]
decimalValue];// Need to change according sample // 1.5 for 10 , 0.75 for 20
plot.barWidth = CPTDecimalFromDouble(barwidht);
plot.barOffset = [[NSDecimalNumber decimalNumberWithString:@"5.0"]
decimalValue];
plot.barCornerRadius = 0.0;
// Remove bar outlines
CPTMutableLineStyle *borderLineStyle = [CPTMutableLineStyle lineStyle];
borderLineStyle.lineColor = [CPTColor clearColor];
plot.lineStyle = borderLineStyle;
plot.identifier = @"chocoplot";
[self.graph addPlot:plot];
}
#pragma mark - core plot data source and delegate methods
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
if ( [plot.identifier isEqual:@"chocoplot"] )
return [self.data count];
return 0;
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
if ( [plot.identifier isEqual:@"chocoplot"] )
{
NSDictionary *bar = [self.data objectAtIndex:index];
if(fieldEnum == CPTScatterPlotFieldX)
return [bar valueForKey:BAR_POSITION];
else if(fieldEnum ==CPTScatterPlotFieldY)
return [bar valueForKey:BAR_HEIGHT];
}
return [NSNumber numberWithFloat:0];
}
drawDownlinkGraph
method would be called each second using a timer and it will call generateBarPlotForDownlink:
Method every second . And bar will be drawn each second on a real time basis even if APP is in background.
Upvotes: 0
Reputation: 27381
You don't need to create a new graph every time you get new plot data. Just add the new point to the data
array and call -reloadData
on the plot.
When the app goes into the background, just clear your data
array and call -reloadData
on the plot. It will reload the empty data and display the graph when the app comes back to the foreground. There's no reason to set self.graph
to nil
unless you remove the graph from the hosting view and you want it to go away. From what I can see in the posted code, the graph is still in the hosting view, but you've lost your reference to it, making any updates you make when the app comes to the foreground ineffective.
Upvotes: 2