大佬教程收集整理的这篇文章主要介绍了iphone – UICollectionView Cell Image随着GCD进入视图而改变,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
在下面的代码中,collectionView将平滑滚动,但有时如果我滚动得非常快,则会显示一个不正确的图像,然后在滚动减速时更改为正确的图像.为什么不将cell.cellImage.image设置为nil修复此问题?
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemATindexPath:(NSIndexPath *)indexPath { CustomTabBarCell *cell = [collectionView dequeueReusableCellWithReusEIDentifier:@"CustomTabBarCell" forIndexPath:indexPath]; cell.cellImage.image = nil; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0ul); dispatch_async(queue,^{ cell.cellImage.image = nil; UIImage *test = [self.optionArray objectATindex:indexPath.row]; UIImage *localImage2 = [self imageWithImage:test scaledToSize:CGSizeMake(test.size.width/5,test.size.height/5)]; dispatch_sync(dispatch_get_main_queue(),^{ cell.cellImage.image = localImage2 cell.cellTextLabel.text = @""; [cell setNeedsLayout]; }); }); } return cell; } - (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSizE)newSize { UIGraphicsBeginImageContextWithOptions(newSize,NO,0.0); [image drawInRect:CGRectMake(0,newSize.width,newSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }
编辑:
我添加了另一个async来缓存第一个和nil并初始化了cell.image.我在初始快速向下滚动时遇到了同样的问题.然而,在卷轴上,它现在完美无瑕.
我补充说:
-(void)createDictionary { for (UIImage *test in self.optionArray) { UIImage *shownImage = [self imageWithImage:test scaledToSize:CGSizeMake(test.size.width/5,test.size.height/5)]; [localImageDict setObject:shownImage forKey:[NSnumber numberWithInt:[self.optionArray indexOfObject:test]]]; } } - (void)viewDidLoad { [super viewDidLoad]; if (!localImageDict) { localImageDict = [[NSMutableDictionary alloc]initWithCapacity:self.optionArray.count]; } else { [localImageDict removeAllObjects]; } dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0ul); dispatch_async(queue,^{ [self createDictionary]; }); } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemATindexPath:(NSIndexPath *)indexPath { CustomTabBarCell *cell = [collectionView dequeueReusableCellWithReusEIDentifier:@"CustomTabBarCell" forIndexPath:indexPath]; cell.cellImage.image = nil; cell.cellImage.image = [[UIImage alloc]init]; if ([localImageDict objectForKey:[NSnumber numberWithInt:indexPath.row]]) { cell.cellImage.image = [localImageDict objectForKey:[NSnumber numberWithInt:indexPath.row]]; cell.cellTextLabel.text = @""; } else { cell.cellImage.image = nil; cell.cellImage.image = [[UIImage alloc]init]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0ul); dispatch_async(queue,^{ UIImage *test = [self.optionArray objectATindex:indexPath.row]; UIImage *shownImage = [self imageWithImage:test scaledToSize:CGSizeMake(test.size.width/5,test.size.height/5)]; [localImageDict setObject:shownImage forKey:[NSnumber numberWithInt:indexPath.row]]; dispatch_sync(dispatch_get_main_queue(),^{ cell.cellImage.image = shownImage; cell.cellTextLabel.text = @""; [cell setNeedsLayout]; }); }); } } return cell;
要减少应用程序的占用空间,您不应该维护一组UIImage对象.相反,只需维护一个URL或路径到您的图像,然后只在UI需要时动态创建UIImage对象(一个称为延迟加载的过程).一旦图像离开屏幕,就可以释放它(UICollectionView,就像UITableView为你做的很多清理工作一样,只要你不保持对图像的强引用).
应用程序通常只应维护当前可见图像的UIImage对象.您可能出于性能原因缓存这些已调整大小的图像(例如,@R_801_11350@SCachE),但是当内存不足时,将自动清除缓存.
好的是你显然已经精通异步处理.无论如何,实现可能如下所示:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemATindexPath:(NSIndexPath *)indexPath { CustomTabBarCell *cell = [collectionView dequeueReusableCellWithReusEIDentifier:@"CustomTabBarCell" forIndexPath:indexPath]; NSString *filename = [self.filenameArray objectATindex:indexPath.row]; // I always use indexPath.item,but if row works,that's great UIImage *image = [self.thumbnailCache objectForKey:filename]; // you can key this on whatever you want,but the filename works cell.cellImage.image = image; // this will load cached image if found,or `nil` it if not found if (image == nil) // we only need to retrieve image if not found in our cache { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,^{ UIImage *test = [UIImage imageWithContentsOfFile:filename]; // load the image here,@L_944_18@ that we k@L_944_18@ we need it if (!test) { NSLog(@"%s: unable to load image",__FUNCTION__); return; } UIImage *localImage2 = [self imageWithImage:test scaledToSize:CGSizeMake(test.size.width/5,test.size.height/5)]; if (!localImage2) { NSLog(@"%s: unable to convert image",__FUNCTION__); return; } [self.thumbnailCache setObject:localImage2 forKey:filename]; // save the image to the cache dispatch_async(dispatch_get_main_queue(),^{ // async is fine; no need to keep this BACkground operation alive,waiTing for the main queue to respond // see if the cell for this indexPath is still onscreen; probably is,but just in case CustomTabBarCell *updateCell = (id)[collectionView cellForItemATindexPath:indexPath]; if (updateCell) { updateCell.cellImage.image = localImage2 updateCell.cellTextLabel.text = @""; [updateCell setNeedsLayout]; } }); }); } return cell; }
这假定您定义了thumbnailCache的类属性,它是对您将在viewDidLoad或其中任何位置初始化的NSCache的强引用.缓存是一种充分利用两个世界的方法,在内存中加载图像以获得最佳性能,但是当您遇到内存压力时它将被释放.
显然,我很乐意假设“哦,只需用一系列图像文件名替换你的图像阵列”,我知道你可能需要进入代码的一些不同部分才能使它工作,但是这个毫无疑问是你的记忆消耗的来源.很明显,你总是会遇到其他内存问题(保留周期等),但在你发布的代码片段中没有类似内容.
以上是大佬教程为你收集整理的iphone – UICollectionView Cell Image随着GCD进入视图而改变全部内容,希望文章能够帮你解决iphone – UICollectionView Cell Image随着GCD进入视图而改变所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。