UICollectionView滚动很慢

我刚刚创建了一个UICollectionView ,用户可以将手机中的图像添加到应用程序中的相册function中。 我将图像保存到文档目录中的子目录中,因此可以添加和删除更多图像。 但是,当我向上和向下滚动集合视图时,它非常迟钝。

如何使滚动变得美观和流畅?

我的代码:前16个图像是预设图像,之后的所有内容都来自文档目录中的子目录

 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Custom" forIndexPath:indexPath]; //Current index number int index=indexPath.section * noOfSection + indexPath.row; //Check if its the preset photos if(index<16){ NSString *name=[recipePhotos objectAtIndex:indexPath.section * noOfSection + indexPath.row]; cell.imageView.image=[UIImage imageNamed:name]; } //not preset photos, so retrieve the photos the user added else { NSData *data= [NSData dataWithContentsOfFile:[recipePhotos objectAtIndex:index]]; UIImage *theImage=[UIImage imageWithData:data]; cell.imageView.image=theImage; data=nil; } return cell; } 

Time Profiler给了我这个

 Running Time Self Symbol Name 568.0ms 63.1% 0.0 Main Thread 0x4048 320.0ms 35.5% 0.0 _pthread_start 0x405e 320.0ms 35.5% 0.0 thread_start 320.0ms 35.5% 0.0 _pthread_start 320.0ms 35.5% 0.0 0x1084be960 310.0ms 34.4% 1.0 0x1084be6f0 7.0ms 0.7% 0.0 mach_msg 2.0ms 0.2% 2.0 objc_msgSend 1.0ms 0.1% 1.0 -[NSAutoreleasePool release] 4.0ms 0.4% 0.0 _dispatch_mgr_thread 0x4052 4.0ms 0.4% 0.0 _dispatch_mgr_thread 4.0ms 0.4% 0.0 _dispatch_mgr_invoke 4.0ms 0.4% 4.0 kevent 3.0ms 0.3% 0.0 _dispatch_worker_thread2 0x62b24 3.0ms 0.3% 1.0 start_wqthread 3.0ms 0.3% 0.0 _dispatch_worker_thread2 0x62a84 3.0ms 0.3% 0.0 start_wqthread 3.0ms 0.3% 0.0 _pthread_wqthread 3.0ms 0.3% 0.0 _dispatch_worker_thread2 3.0ms 0.3% 0.0 _dispatch_queue_invoke 3.0ms 0.3% 0.0 _dispatch_queue_drain 3.0ms 0.3% 0.0 _dispatch_client_callout 2.0ms 0.2% 0.0 my_io_execute_passive_block 1.0ms 0.1% 0.0 __86-[NSPersistentUIManager writePublicPlistWithOpenWindowIDs:optionallyWaitingUntilDone:]_block_invoke_0835 1.0ms 0.1% 0.0 -[NSPersistentUIManager writePublicPlistData:] 1.0ms 0.1% 0.0 -[NSURL(NSURLPathUtilities) URLByAppendingPathComponent:] 1.0ms 0.1% 0.0 -[NSURL getResourceValue:forKey:error:] 1.0ms 0.1% 0.0 CFURLCopyResourcePropertyForKey 1.0ms 0.1% 0.0 __block_global_2 1.0ms 0.1% 0.0 -[NSPersistentUIManager writeRecords:withWindowInfos:flushingStaleData:] 1.0ms 0.1% 0.0 _dispatch_call_block_and_release 1.0ms 0.1% 0.0 0x1084b8580 1.0ms 0.1% 0.0 mach_msg_send 1.0ms 0.1% 0.0 mach_msg 1.0ms 0.1% 1.0 mach_msg_trap 1.0ms 0.1% 0.0 _pthread_struct_init 0x62a83 1.0ms 0.1% 0.0 start_wqthread 1.0ms 0.1% 0.0 _pthread_wqthread 1.0ms 0.1% 1.0 _pthread_struct_init 1.0ms 0.1% 0.0 start_wqthread 0x62a7f 

您需要在tableviews中创建一个类似于您需要执行的操作的方法,您将需要重用视图,就像在表视图中重用您的单元格一样。

Ray Wenderlich提供了一个非常好的教程:

在第一部分你有基本的,在第二部分他们谈论可重用的视图,你,看看链接:

http://www.raywenderlich.com/22417/beginning-uicollectionview-in-ios-6-part-22

编辑

加载图像异步的示例:

例如,在您的单元格中创建一个方法loadImageFromFile ,它接收您将以这种方式调用它的路径:

 [cell loadImageFromFile:[recipePhotos objectAtIndex:index]]; 

然后看起来像(也许你需要适应一些东西……):

 - (void) loadImageFromFile:(NSString*)path{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{ NSData *data= [NSData dataWithContentsOfFile:path]; UIImage *theImage=[UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ cell.imageView.image=theImage; }); }); 

@ggrana有正确的想法。 加载异步肯定会有所帮助。 但是,如果每次都从文件加载,那么您仍在进行冗余工作。 要考虑的一件事是使用NSCache增加异步加载。 它基本上是一个NSDictionary但它本身就是内存管理,并在存在内存压力时转储数据。

因此,如果你有内存预算,你可以实时制作缩略图(这样你就不必硬编码大小)并将它们存储在缓存中。 这样你的图像只会在第一次弹出。 每次之后,他们立即加载。

您可以像这样使用它:

 @implementation ... { NSCache * _johnny; // get it? } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { [cell setImage:nil]; // since they are reused, prevents showing an old image dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ UIImage * sticker = [self thumbnailOfSize:CGSizeMake(desiredImageWidth, desiredImageHeight) forIndex:[indexPath row]]; dispatch_async(dispatch_get_main_queue(), ^{ [cell setImage:sticker]; }); }); } // load image from disk and cache thumbnail version - (UIImage*) thumbnailOfSize:(CGSize)size forIndex:(NSInteger)index { NSString * cacheKey = [NSString stringWithFormat:@"%@ %d", NSStringFromCGSize(size), index]; UIImage * image = [_johnny objectForKey:cacheKey]; if (!image) { image = [UIImage imageWithContentsOfFile:_imagePaths[index]]; float desiredWidth = size.width; float desiredHeight = size.height; float actualHeight = image.size.height; float actualWidth = image.size.width; float imgRatio = actualWidth / actualHeight; float maxRatio = desiredWidth / desiredHeight; if(imgRatio != maxRatio) { if(imgRatio < maxRatio) { imgRatio = desiredHeight / actualHeight; actualWidth = imgRatio * actualWidth; actualHeight = desiredHeight; } else { imgRatio = desiredWidth / actualWidth; actualHeight = imgRatio * actualHeight; actualWidth = desiredWidth; } } CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight); UIGraphicsBeginImageContextWithOptions(rect.size, FALSE, 0); // do right thing for retina [image drawInRect:rect]; image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // here's johnny [_johnny setObject:image forKey:cacheKey]; } return image; } 

所以在经历了一些混乱后,我发现问题是基于几个因素。

一个 – 缩略图的图像太大,所以我所做的是制作了一个单独的图像arrays,图像尺寸较小,适合细胞。 二 – 在@ggrana的帮助下,打开一个单独的线程加快了流程,使其不那么迟钝。 三 – 我还发现拥有一组图像而不是图像位置更快 – 唯一的问题是它占用了更多的内存。