YogiAR
YogiAR

Reputation: 2237

Core plot : bars disappears when switching app to background and then to foreground while drawing a bar graph

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:

enter image description here

Upvotes: 2

Views: 122

Answers (2)

YogiAR
YogiAR

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

Eric Skroch
Eric Skroch

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

Related Questions