iphoneios8core-graphicscore-plot

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


Solution

  • 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.