核心情节:在绘制条形图时将应用程序切换到背景然后再切换到前景时条形消失

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

当我将我的应用程序切换到后台然后又回到前台时,我的条形图消失了。

如下图所示:

|||        ||   || 

所以在上图中我有间隙,这意味着当我的应用程序处于后台时核心图不会绘制条形图。是不是核心剧情的限制?

我的主要任务是每秒绘制一个柱状图,我已经做到了,但是在后台无法正常工作。我可以通过其他替代方案实现这一目标吗?

这是我尝试过的:

我将图形对象设置为 nil,然后尝试在应用程序再次返回前台时重新加载它。但是没用。

 -(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];
}`

这是我的完整代码:

// 更新由计时器(10 秒)调用,因此每秒都会调用此方法并绘制一个条形。

- (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]];
    
}

截图:

您无需在每次获得新的绘图数据时都创建新图表。只需将新点添加到 data 数组并在图上调用 -reloadData

当应用程序进入后台时,只需清除 data 数组并在绘图上调用 -reloadData。当应用程序返回前台时,它将重新加载空数据并显示图形。没有理由将 self.graph 设置为 nil ,除非您从托管视图中删除图表并希望它消失。从我在发布的代码中看到的,该图仍在托管视图中,但您已经丢失了对它的引用,这使得您在应用程序进入前台时所做的任何更新都无效。

这是对我有用的代码:

- (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 方法将使用计时器每秒调用一次,它会每秒调用 generateBarPlotForDownlink: 方法。即使APP在后台,也会实时绘制柱状图。