我知道这听起来很奇怪,但问题恰恰在于:我有一个ViewController
加载与Grand Central Dispatch异步的CSV文件(该文件代表一个直方图)。我还有一个名为HistogramView
的自定义视图。当控制器完成加载CSV文件时,它会调用invalidate
上的函数HistogramView
。在该函数中,视图解析从文件读取的数据并创建:
对于形状图层没有问题,一切都很好。文本图层出现问题:最初只显示背景。文本只在几秒钟后出现: - /这很奇怪。这是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];
}
});
}
答案 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];
}];
}
});
}