Загрузка изображения из локального хранилища в CollectionView


#1

Как реализовать загрузку изображений из локального хранилища в CollectionView при старте приложения?
В гугле я не нашел подобных реализаций, подскажите или скиньте необходимый ресурс


#2
  1. Создай массив из названий изображений.
  2. Создай класс для ячейки CollectionView
  3. Положи UIImage на ячейку CollectionView и создай для него аутлет в классе для ячейки.
  4. Подпиши свой класс UIViewController в котором находится CollectionView на протокол UICollectionViewDataSource
  5. Определи для CollectionView.dataSource = self (это твой вьюконтроллер)
  6. Реализуй два метода протокола: 1 - UICollectionViewDataSource - collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) здесь нужно вернуть количество ячеек для CollectionView, оно будет равнятся количеству элементов массива с названиями твоих изображений, 2 - collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell - здесь тебе и нужно настроить свою ячейку, присвоить картинку и возратить готовую ячейку.

Как то так.


#3

Имеется виду, достать все фото из галереи и загрузить в collectionView


#4
var allPhotos: PHFetchResult<PHAsset>!
let photosCountInRow: CGFloat = 4

func viewDidLoad() {
    let allPhotosOptions = PHFetchOptions()
    allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    self.allPhotos = PHAsset.fetchAssets(with: allPhotosOptions)
    PHPhotoLibrary.shared().register(self)
}

func photoLibraryDidChange(_ changeInstance: PHChange) {
        guard let changes = changeInstance.changeDetails(for: allPhotos) else { return }
    
    // Change notifications may be made on a background queue. Re-dispatch to the
    // main queue before acting on the change as we'll be updating the UI.
    DispatchQueue.main.sync {
        // Hang on to the new fetch result.
        allPhotos = changes.fetchResultAfterChanges
        
        // to avoid such errors we should just call reloadData()
        // Fatal Exception: NSInternalInconsistencyException
        // attempt to delete and reload the same index path
        // (<NSIndexPath: 0x1d0431720> {length = 2, path = 0 - 1})
        self.uiPhotoCollectionView?.reloadData()
    }
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return allPhotos == nil ? 0 : allPhotos.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let asset = allPhotos.object(at: indexPath.item)
    let layoutAttributes = collectionView.collectionViewLayout.layoutAttributesForItem(at: indexPath)
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CellIdentifier", for: indexPath) as! CollectionViewCellClass
    
    cell.indexPath = indexPath
    cell.photoAsset = asset
    cell.size = layoutAttributes.frame.size
    
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0.5
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 0.5
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = collectionView.frame.width

    return CGSize(width: width/photosCountInRow - 0.5, height: width/photosCountInRow - 0.5)
}


class CollectionViewCellClass: UICollectionViewCell {

    private let scale = UIScreen.main.scale

    var photoAsset: PHAsset? {
        didSet {
            loadPhotoAssetIfNeeded()
        }
    }

    var size: CGSize? {
        didSet {
            loadPhotoAssetIfNeeded()
        }
    }

    var indexPath: IndexPath?
    private var imageRequestID: PHImageRequestID?

    override func prepareForReuse() {
        super.prepareForReuse()
        uiPhotoView.image = nil
        
        //Cancel requests if needed
        let manager = PHImageManager.default()
        guard let imageRequestID = self.imageRequestID else { return }
        manager.cancelImageRequest(imageRequestID)
        self.imageRequestID = nil
    }

    private func loadPhotoAssetIfNeeded() {
        guard let indexPath = self.indexPath,
            let asset = photoAsset, let size = self.size else { return }
        
        let options = PHImageRequestOptions()
        options.deliveryMode = .highQualityFormat
        options.resizeMode = .fast
        options.isSynchronous = false
        options.isNetworkAccessAllowed = true
        
        let manager = PHImageManager.default()
        let newSize = CGSize(width: size.width * scale,
                             height: size.height * scale)
        
        imageRequestID = manager.requestImage(for: asset, targetSize: newSize, contentMode: .aspectFill, options: options, resultHandler: { [unowned self] (result, _) in
            guard self.indexPath?.item == indexPath.item else { return }
            self.imageRequestID = nil
            UIView.transition(with: self.uiPhotoView,
                              duration: 0.3,
                              options: .transitionCrossDissolve,
                              animations: { self.uiPhotoView.set(image: result, focusOnFaces: false) },
                              completion: nil)
        })
    }
}

#5

ок гугли как достать фотки из галереи и применяй мой описаный метод