I\'m struggling with the problem of displaying photo gallery from iPhone to collectionView
.
Everything works fine if someone has 50 photos inside t
Have you looked into SDWebImage? It has built in cache support so that the device doesn't have to download images it has previously downloaded every single time. It also has the benefit of being very simple to implement!
What you need is to add a fetchResult property to your collection view controller and fetch your image Assets inside viewDidLoad method.
var fetchResult: PHFetchResult<PHAsset> = PHFetchResult()
func fetchAssets() {
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
}
override func viewDidLoad() {
super.viewDidLoad()
fetchAssets()
}
Next step is extend UIImageView to request the image data asynchronously setting its image on completion.
extension UIImageView {
func fetchImage(asset: PHAsset, contentMode: PHImageContentMode, targetSize: CGSize, version: PHImageRequestOptionsVersion = .current, deliveryMode: PHImageRequestOptionsDeliveryMode = .opportunistic) {
let options = PHImageRequestOptions()
options.version = version
options.deliveryMode = deliveryMode
PHImageManager.default().requestImage(for: asset, targetSize: targetSize, contentMode: contentMode, options: options) { image, _ in
guard let image = image else { return }
switch contentMode {
case .aspectFill: self.contentMode = .scaleAspectFill
case .aspectFit: self.contentMode = .scaleAspectFit
@unknown default: fatalError()
}
self.image = image
}
}
}
Now you can fetch the images one at a time inside collection view cellForItemAt method:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CollectionViewCell
let asset = fetchResult.object(at: indexPath.row)
cell.imageView.fetchImage(asset: asset, contentMode: .aspectFill, targetSize: cell.imageView.frame.size * UIScreen.main.scale )
return cell
}
Don't forget to return the fetchResult count for numberOfItemsInSection method.
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return fetchResult.count
}
class CollectionViewCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
}
extension CGSize {
static func *(lhs: CGSize, rhs: CGFloat) -> CGSize {
.init(width: lhs.width * rhs, height: lhs.height * rhs)
}
}