UICollectionView scroll slowly

I just created a UICollectionView in which a user can add images from his phone to the photo album function in the application. I have saving images in a subdirectory in the document directory so that I can add and delete more. However, when I look at the view and view the collection, it is very backward.

How to make a scroll pleasant and smooth?

My code: the first 16 images are predefined images after that from a subdirectory in the document directory

 - (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 gave me this

 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 
+7
source share
3 answers

So, after some involvement, I found out that the problem was based on several factors.

One. The images for the thumbnails were too large, so I made a separate array of images with smaller image sizes that would fit the cell. Two. With @ggrana, opening a separate thread accelerated the process and made it less laggy. Three - I also found that having an array of images, rather than image locations, was faster - the only problem is that it takes up more memory.

+2
source

You will need to make an approach such as the one you need to do in the table view, you will need to reuse the views, for example, you reuse your cells as a table.

A really good tutorial is one of Ray Wenderlich:

In the first part, you have a basic one, in the second - talk about multiple views, you look at the link:

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

Edit

An example of loading async images:

Create a loadImageFromFile method in your cell, for example, which will get the path that you specify as follows:

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

And then it will look (maybe you need to adapt something ...):

 - (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; }); }); 
+3
source

@ggrana has the right idea. Downloading async will definitely help. However, you still do redundant work if you download from a file each time. One thing to consider is to increase async load with NSCache . This is basically an NSDictionary , but memory management itself resets data when there is memory pressure.

So, if you have a memory budget, you can make your thumbnails on the fly (so you don’t need to hardcode the size) and store them in the cache. Thus, your images only appear for the first time. Each time after that they instantly load.

You can use it like this:

 @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 johnny [_johnny setObject:image forKey:cacheKey]; } return image; } 
+3
source

All Articles