collectionView pictures not appearing without sliding

The collectionView pictures only start appearing if I slide them horizontally to the left. I've tried numerous solutions but couldn't solve it. If I assign the collectionView cells a background color, it works perfectly. But assigning the image of the "photoImageView" causes the problem. I must be missing something. "collectionView.reloadData()" doesn't solve the problem. Any advice please ?


import Foundation

import UIKit

import Photos


class PhotoViewController: UIViewController {


@IBOutlet weak var photoImageView: UIImageView!

@IBOutlet weak var peeTabBar: UITabBar!

@IBOutlet var photoView: UIView!


var imagePicker = UIImagePickerController()



override func viewDidLoad() {

super.viewDidLoad()


imagePicker.delegate = self

assignTap()


view.addSubview(collectionView)

collectionView.backgroundColor = .white

collectionView.topAnchor.constraint(equalTo: photoImageView.bottomAnchor, constant: 110).isActive = true

collectionView.clipsToBounds = true

collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true

collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 10).isActive = true

collectionView.bottomAnchor.constraint(equalTo: peeTabBar.topAnchor, constant: -20).isActive = true


collectionView.dataSource = self

collectionView.delegate = self



}


func assignTap() {

let tap = UITapGestureRecognizer(target: self, action: #selector(touchTapped(_:)))

photoView.addGestureRecognizer(tap)


}


@objc func touchTapped(_ sender: UITapGestureRecognizer) {


peeTabBar.isHidden = !peeTabBar.isHidden

}

func chooseImage(_ sender: Any) {


if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {

imagePicker.sourceType = .photoLibrary

imagePicker.allowsEditing = true

self.present(imagePicker,animated: true, completion: nil)

}

}


func accessVideo(_ sender: Any) {


if UIImagePickerController.isSourceTypeAvailable(.camera) {

imagePicker.sourceType = .camera

self.present(imagePicker, animated: true, completion: nil)

} else {

print("Camera not available")

}

}


public func chooseLastImage(_ sender: Any) {


print("photoImageView", photoImageView!)

print("photoImageView.bounds", photoImageView.bounds)


let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width, height: photoImageView.bounds.height)

let options = PHImageRequestOptions()

options.isNetworkAccessAllowed = true

options.deliveryMode = .highQualityFormat


let imgManager = PHImageManager.default()

let fetchOptions = PHFetchOptions()

fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)]


let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)


print("targetSize for request", targetSize!) //What is its value

imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in

guard let result = result else { return }


DispatchQueue.main.async(execute: {

self.photoImageView.image = result

})

}

}


fileprivate let collectionView: UICollectionView = {

let layout = UICollectionViewFlowLayout()

layout.scrollDirection = .horizontal

let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)

cv.translatesAutoresizingMaskIntoConstraints = false

cv.register(CustomCell.self, forCellWithReuseIdentifier: "PreviewCell")

return cv

}()

}


extension PhotoViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

return CGSize(width: collectionView.frame.width/5, height: collectionView.frame.width/4)

}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

return 11

}


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewCell", for: indexPath) as! CustomCell

DispatchQueue.main.async {

cell.bgImage = self.photoImageView.image

}

return cell

}


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

return UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5)

}


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

return 5

}


}


class CustomCell: UICollectionViewCell {


fileprivate let bg: UIImageView = {

let iv = UIImageView()


iv.translatesAutoresizingMaskIntoConstraints = false

iv.contentMode = .scaleAspectFit

iv.clipsToBounds = true

return iv

}()


var bgImage: UIImage? {

get {

bg.image

}

set {

bg.image = newValue

}

}


override init(frame: CGRect) {

super.init(frame: frame)


contentView.addSubview(bg)

bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true

bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true

bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true

bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true


}


required init?(coder: NSCoder) {

fatalError("init(coder:) has not been implemented")

}

}


extension PhotoViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {


if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {

photoImageView.image = image

}

dismiss(animated: true, completion: nil)


}


func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {

dismiss(animated: true, completion: nil)

}


}

Replies

First of all, please learn how to format your code using the button `<>` over the editor area.


Second, please clarify when do you want to show the image in the cell?

When your app start, `photoImageView` is not given an image, so the collection view shows cells with bg empty.


You have some code setting `photoImageView.image`, in `chooseLastImage(_:)` or `UIImagePickerControllerDelegate` invoked through `chooseImage(_:)`, but I cannot find any code calling such methods.


And you say "collectionView.reloadData()" doesn't solve the problem, but you are not showing the code calling `reloadData()`.


Generally, `reloadData()` does work when you want to update all the contents of the cells. So, if you want to update the collection view immediately after the image of `photoImageView` is updated, you call `reloadData()` there.

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        
        if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            
            photoImageView.image = image
            collectionView.reloadData()
        }
        dismiss(animated: true, completion: nil)
        
    }

Or:

    public func chooseLastImage(_ sender: Any) {

        //...        
        
        print("targetSize for request", targetSize!)          //What is its value
        imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in
            
            guard let result = result else { return }
            
            DispatchQueue.main.async(execute: {
                self.photoImageView.image = result
                self.collectionView.reloadData()
            })
        }
    }

If you have other codes updating `photoImageView.image`, you may need to put `reloadData()` there.

Sorry for sending unindented. I tried "collectionView.reloadData()" in viewDidLoad(). Obviously, I was wrong. Thank you very much for your help.