【发布时间】:2014-12-12 08:36:08
【问题描述】:
我知道这听起来很奇怪,但问题恰恰在于:我有一个ViewController,它加载一个与 Grand Central Dispatch 异步的 CSV 文件(该文件代表一个直方图)。我还有一个名为HistogramView 的自定义视图。当控制器完成加载 CSV 文件时,它会在 HistogramView 上调用函数 invalidate。在该函数中,视图解析从文件中读取的数据并创建:
- 一些表示直方图条形的 CAShapeLayer
- 一些表示条形标签的 CATextLayer
对于形状层没问题,一切都很好。文本层出现问题:最初只显示背景。文本仅在几秒钟后出现:-/ 这很奇怪。这是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];
}
});
}
【问题讨论】:
-
主线程是否调用了invalidate?
-
嗯...实际上没有。因为我传递给视图的数据是从读取的异步文件中加载的(感谢 Grand Central Dispatch)。我从 dispatch_io_read 末尾执行的代码块中调用“无效”。检查我的编辑。那是问题吗?感谢您的帮助!
标签: ios objective-c view core-graphics cashapelayer