I have a gallery in my app utilizing a UICollectionView
. The cells are approximately 70,70 size. I am using ALAssets
from the ALAssetLibrary
in the gallery which I have stored in a list.
I am using the usual pattern for populating the cells:
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
mycell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
mycell.imageView.image = [[UIImage imageWithCGImage:[alassetList objectAtIndex:indexpath.row] thumbnail]];
return mycell;
}
My gallery is scrolling choppy. I don't understand why this is. I've tried adding a NSCache to cache the thumbnail images (thinking maybe creating the images was expensive) but this did not help for the performance.
I would expect the UI to be as buttery as the stock app.
I am now suspecting it may be something in the UICollectionViewCell prepareForReuse
that may be holding up the dequeueReusableCellWithReuseIdentifier
method but using instruments I was not able to find this.
Any other thing that may be be causing this? Is there a "faster" way to prepare the UICollectionViewCell
or to dequeue
them in a faster fashion?
So anybody having scrolling issues should do this
add these 2 lines after your dequeue
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
I would assume the "choppyness" is coming from the UIImage allocation, not anything with the dequeueReusableCellWithReuseIdentifier
method. I'd try doing the image allocation on a background thread and see if that makes things a little more buttery.
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
mycell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
// Load image on a non-ui-blocking thread
UIImage *image = [[UIImage imageWithCGImage:[alassetList objectAtIndex:indexpath.row] thumbnail]];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
// Assign image back on the main thread
mycell.imageView.image = image;
});
});
return mycell;
}
More details can be found here: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html
Load your images using NSURLConnection's sendAsynchronousRequest:queue:completionHandler:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
[cell.imageView setImage:[UIImage imageWithData:data]];
}];
Tick on clip subviews and opaque in attributes inspector and tick off paging enabled.
If anyone is using PhImageManager, turning off synchronous solved the problem. (deliveryMode = .FastFormat can also give additional performance enhancement, but the tradeoff is the thumbnail will be of lower quality)
let option = PHImageRequestOptions()
option.deliveryMode = .Opportunistic
option.synchronous = false
PHImageManager().requestImageForAsset(phAsset, targetSize: CGSizeMake(2048, 2048), contentMode: .AspectFit, options: option, resultHandler: { (image, objects) in
self.imageView.image = image!
})
I had issues with UICollectionView
scrolling.
What worked (almost) like a charm for me: I populated the cells with png thumbnails 90x90. I say almost because the first complete scroll is not so smooth, but never crashed anymore...
In my case, the cell size is 90x90.
I had many original png sizes before, and it was very choppy when png original size was greater than ~1000x1000 (many crashes on first scroll).
So I select 90x90 (or the like) on the UICollectionView
and display the original pngs (no matter the size). Hope this helps others.
I'll share my experience working with collection views.
Swift 5
If you are running iOS 10+, performance should already be better than what you had on earlier versions of iOS. I highly recommend you watch this WWDC video - What's New in UICollectionView in iOS 10
One really simple thing that improved my performance was just implementing the prefetching delegate. I did literally nothing other than just implement it!
First make sure your collectionView conforms to the delegate,
yourCollectionView.prefetchDataSource = self
Then just implement the prefetching delegate,
extension YourViewController: UICollectionViewDataSourcePrefetching { func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) { // You could do further optimizations here. } }
来源:https://stackoverflow.com/questions/18460655/uicollectionview-scrolling-choppy-when-loading-cells