CATextLayer仅在一段时间后才显示其内容

时间:2014-12-11 18:12:06

标签: ios objective-c view core-graphics cashapelayer

我知道这听起来很奇怪,但问题恰恰在于:我有一个ViewController加载与Grand Central Dispatch异步的CSV文件(该文件代表一个直方图)。我还有一个名为HistogramView的自定义视图。当控制器完成加载CSV文件时,它会调用invalidate上的函数HistogramView。在该函数中,视图解析从文件读取的数据并创建:

  1. 代表直方图条形的一些CAShapeLayer
  2. 一些代表条形标签的CATextLayer
  3. 对于形状图层没有问题,一切都很好。文本图层出现问题:最初只显示背景。文本只在几秒钟后出现: - /这很奇怪。这是invalidate函数的代码(正如我所说,这个函数在自定义视图中)。

    -(void)invalidate{
        float tempX = 0;
        float tempHeight = 0;
        NSArray *data;
    
        if([self.dataSource getHistogramData] != nil){
            data = [self.dataSource getHistogramData];
            tempX = [self getStartingX];
            [self getDataMaxValue];
    
            for (int i=0; i<[data count]; i+=2) {
    
                //THE SHAPE LAYER THAT REPRESENTS AN HISTOGRAM BAR
                tempHeight = [self uniformValue:[[data objectAtIndex:i+1] intValue]];
                CAShapeLayer *rectLayer = [CAShapeLayer layer];
                CGRect rect = CGRectMake(tempX, tempHeight, barWidth, height - tempHeight - spaceForLabels);
                rectLayer.path = CGPathCreateWithRect(rect, nil);
                [rectLayer setBackgroundColor:[UIColor colorWithRed:1 green:1 blue:1 alpha:1].CGColor];
                [self.layer addSublayer:rectLayer];
    
    
                //THE TEXT LAYER THAT REPRESENTS A LABEL FOR THE BAR
                CATextLayer *textLayer = [CATextLayer layer];
                textLayer.frame = CGRectMake(tempX, height - spaceForLabels, barWidth, spaceForLabels);
                textLayer.font = CFBridgingRetain([UIFont boldSystemFontOfSize:18].fontName);
                textLayer.fontSize = 18;
                textLayer.foregroundColor = [UIColor redColor].CGColor;
                textLayer.backgroundColor = [UIColor yellowColor].CGColor;
                textLayer.alignmentMode = kCAAlignmentCenter;
                textLayer.string = @"example";
                [self.layer addSublayer:textLayer];
    
    
                tempX += barWidth + spaceBetweenBars;
            }
    
        }
    }
    

    如您所见,我以相同的方式和同一点创建条形和标签。提前谢谢。

    在我的视图控制器中

    编辑我以viewDidLoad方式执行此工作:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        //create the channel with which read the CSV file
        dispatch_io_t ch = dispatch_io_create_with_path(DISPATCH_IO_STREAM, [[[NSBundle mainBundle] pathForResource:@"histogram1" ofType:@"csv"] UTF8String], O_RDONLY, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), nil);
    
        //read the CSV file async with GCD
        [self readCSVFile:ch];
    
        //set the delegates for the histogram view
        self.histogramView.delegate = self;
        self.histogramView.dataSource = self;
    }
    
    -(void)readCSVFile:(dispatch_io_t)ch{
    
        //the string that represents the content of CSV file
        NSMutableString __block *stringFromData;
    
        //read the whole file
        dispatch_io_read(ch, 0, SIZE_MAX, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(bool done, dispatch_data_t dataRead, int error) {
    
            if(!error && !done){
    
                //convert from dispatch_data_t to NSString
                size_t dataSize = dispatch_data_get_size(dataRead);
                stringFromData = [[NSMutableString alloc]initWithCapacity:dataSize];
                dispatch_data_apply(dataRead, ^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) {
                    [stringFromData appendFormat:@"%.*s", (unsigned int)size, buffer];
                    return true;
                });
            }else{
                dispatch_io_close(ch, 0);
                data = [stringFromData componentsSeparatedByCharactersInSet:
                           [NSCharacterSet characterSetWithCharactersInString:@"\n,"]];
    
                //AND NOW I CALL INVALIDATE ON THE VIEW
                [self.histogramView invalidate];
            }
    
        });
    }
    

1 个答案:

答案 0 :(得分:0)

好的,我明白了。我要感谢 rdelmar ,他的建议指出了我的问题。正如他所说,invalidate不是从主线程调用,而是从后台线程(读取文件的线程)调用。这是错误的,因为必须从主线程更新View。所以,我通过这种方式简单地调用invalidate方法解决了这个问题:

-(void)readCSVFile:(dispatch_io_t)ch{

    //the string that represents the content of CSV file
    NSMutableString __block *stringFromData;

    //read the whole file
    dispatch_io_read(ch, 0, SIZE_MAX, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(bool done, dispatch_data_t dataRead, int error) {

        if(!error && !done){

            //convert from dispatch_data_t to NSString
            size_t dataSize = dispatch_data_get_size(dataRead);
            stringFromData = [[NSMutableString alloc]initWithCapacity:dataSize];
            dispatch_data_apply(dataRead, ^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) {
                [stringFromData appendFormat:@"%.*s", (unsigned int)size, buffer];
                return true;
            });
        }else{
            dispatch_io_close(ch, 0);
            data = [stringFromData componentsSeparatedByCharactersInSet:
                       [NSCharacterSet characterSetWithCharactersInString:@"\n,"]];

            //HERE IS THE SOLUTION
            [[NSOperationQueue mainQueue]addOperationWithBlock:^{
                [self.histogramView invalidate];
            }];
        }

    });
}