当我向下滚动UITableView时,我正在使用旋转活动指示器来显示进度
加载更多结果。它应该像这样工作:如果我到达数据数组的最后一个索引,UITableView将在下一个单元格上显示一个活动指示器。但是,每当我摆脱旧的数据数组并使用新的数据数组并使用reloadData
时,活动指示器就不会消失。活动指示符将位于另一个现有数据单元格的同一单元格中。在调试窗口中,它显示一些CGContext错误:
<Error>: CGContextSaveGState: invalid context 0x0
<Error>: CGContextSetBlendMode: invalid context 0x0
<Error>: CGContextSetAlpha: invalid context 0x0
<Error>: CGContextTranslateCTM: invalid context 0x0
<Error>: CGContextScaleCTM: invalid context 0x0
<Error>: CGContextDrawImage: invalid context 0x0
<Error>: CGContextRestoreGState: invalid context 0x0
<Error>: CGContextSetRGBFillColor: invalid context 0x0
<Error>: CGContextFillRects: invalid context 0x0
<Error>: CGContextSetFillColorWithColor: invalid context 0x0
<Error>: CGContextSetFont: invalid context 0x0
<Error>: CGContextSetTextMatrix: invalid context 0x0
<Error>: CGContextSetFontSize: invalid context 0x0
<Error>: CGContextSetTextPosition: invalid context 0x0
<Error>: CGContextShowGlyphsWithAdvances: invalid context 0x0
如何解决此问题?
这是我在cellForRowAtIndexPath的代码:
TNSTableViewCell *videoCell = [tableView dequeueReusableCellWithIdentifier:@"videoCell"];
if (videoCell == nil) {
videoCell = [[TNSTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"videoCell"];
}
// When scroll down last index of the index load next page
if (indexPath.row >= self.entries.count) {
if (!loading) {
NSLog(@"Loading new records...");
loading = YES;
if (fetchBatch != 0) {
[informationDownloader getSearchRecordsWithKeywords:nil];
}
}
}
if (indexPath.row < self.entries.count) {
if (videoCell.activityIndicator) {
videoCell.activityIndicator = nil;
}
TNSVideoRecord *record = [self.entries objectAtIndex:[indexPath row]];
videoCell.textLabel.text = record.title;
videoCell.textLabel.backgroundColor = [UIColor clearColor];
videoCell.detailTextLabel.numberOfLines = 2;
videoCell.detailTextLabel.text = [@"views: " stringByAppendingFormat:@"%@\n%@", [record.viewCount stringValue], record.uploader];
videoCell.detailTextLabel.backgroundColor = [UIColor clearColor];
if (!record.image) {
if (self.thumbnailVideoTableView.dragging == NO && self.thumbnailVideoTableView.decelerating == NO) {
[informationDownloader downloadThumbnailForRecord:record];
}
// if a download is deferred or in progress, return a placeholder image
UIImageView *imageView = videoCell.imageView;
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.alpha = 1.0;
indicator.center = imageView.center;
[imageView addSubview:indicator];
[indicator startAnimating];
} else {
videoCell.imageView.image = record.image;
}
videoCell.imageView.userInteractionEnabled = YES;
videoCell.imageView.tag = [indexPath row];
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(playVideo:)];
[videoCell.imageView addGestureRecognizer:tapped];
UIImage *playButtonImage = [UIImage imageNamed:@"playbutton.png"];
NSString *durationText = [TNSUtilities convertDuration:record.length];
UIImage *image = [TNSUtilities drawText:durationText inImage:[TNSUtilities drawImage:playButtonImage inImage:videoCell.imageView.image]];
videoCell.imageView.image = image;
videoCell.accessoryView.tag = [indexPath row];
videoCell.accessoryView = [self makeAddButton];
videoCell.accessoryView.userInteractionEnabled = YES;
[videoCell setNeedsLayout];
} else {
NSLog(@"Displaying spinning indicator.");
videoCell.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
videoCell.activityIndicator.backgroundColor = [UIColor clearColor];
[videoCell addSubview:videoCell.activityIndicator];
videoCell.activityIndicator.frame = CGRectMake(self.view.frame.size.width/2 - 15, videoCell.frame.size.height/2 - 15, 30, 30);
videoCell.backgroundColor = [UIColor clearColor];
[videoCell.activityIndicator startAnimating];
[videoCell setNeedsLayout];
}
return videoCell;
正如您所看到的,imageView中还有另一个活动指示器,在更新数据阵列后该指示器也保留在imageView上。奇怪的是,指标并没有出现在每个uitableviewcell上。
这是我在TNSTableViewCell中的prepareReuse实现,它是UITableViewCell的子类:
- (void)prepareForReuse
{
if (self.activityIndicator) {
[self.activityIndicator stopAnimating];
self.activityIndicator = nil;
}
self.textLabel.text = nil;
self.detailTextLabel.text = nil;
}
这是drawText方法和drawImage方法:
+ (UIImage *)drawText:(NSString *)text inImage:(UIImage *)image
{
UIGraphicsBeginImageContext(image.size);
CGRect bgRect = CGRectMake( 0, 0, image.size.width, image.size.height);
[image drawInRect: bgRect];
CGFloat rectWidth;
if (text.length < 6) {
rectWidth = 40.0f;
} else {
rectWidth = 56.0f;
}
CGRect textRect = CGRectOffset(CGRectMake(0, 0, rectWidth, 14), bgRect.size.width - rectWidth, bgRect.size.height - 14);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 100.0f/255.0f, 100.0f/255.0f, 100.0f/255.0f, 1.0f);
CGContextFillRect(context, textRect);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
[text drawInRect:textRect withFont:[UIFont systemFontOfSize:14] lineBreakMode:NSLineBreakByClipping];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
+ (UIImage *)drawImage:(UIImage *)fgImage inImage:(UIImage *)bgImage
{
UIGraphicsBeginImageContextWithOptions(bgImage.size, FALSE, 0.0);
CGRect bgRect = CGRectMake( 0, 0, bgImage.size.width, bgImage.size.height);
[bgImage drawInRect:bgRect];
[fgImage drawInRect:CGRectOffset(CGRectMake(0, 0, fgImage.size.width, fgImage.size.height), bgRect.size.width/2 - fgImage.size.width/2, bgRect.size.height/2 - fgImage.size.height/2)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
答案 0 :(得分:0)
当您重复使用单元格并添加子视图时,它会保留在那里。因此,下次重复使用时,您需要检查是否有子视图并明确重新使用它。
对于您的活动指示器,当单元格从显示中移除但指示器仍然是动画时,它将尝试绘制而没有有效的上下文。
当电池离开屏幕并重复使用时,请尝试停止/移除指示灯。或者,考虑简化您的单元格设置并使用页脚视图来保存活动指示器,并在完成后删除页脚。