I have UICollectionView in a cell of UITableView. This UICollectionView displays user's profile photos. There are only a few items there (let's assume 10 photos is a maximum).
So, I do not want to reload images from backend every time cell reusing. It's inconvenient and unfriendly UX. Therefore, I want to create 10 cells, load images into them and show.
But I don't know how to create (instead of dequeuing) new custom cells within "cellForItem" method of UICollectionView. Or how to forbid reusing.
I'm a kind of newbie in programming, so I would be glad if you explained me that in simple words and most detailed. Thank you.
Here is my code:
Setting CollectinView (uploading random local photos in testing purpose):
extension PhotosTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AddPhotoCollectionViewCell", for: indexPath)
return cell
} else {
var cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCollectionViewCell", for: indexPath) as! PhotoCollectionViewCell
cell.photo = UIImage(named: "Photo\(Int.random(in: 1...8))") ?? UIImage(named: "defaultPhoto")
cell.layer.cornerRadius = 10
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = collectionView.frame.height
let width = (height / 16.0) * 10.0
return CGSize(width: width, height: height)
}
}
My custom PhotoCollectionViewCell:
class PhotoCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var heightConstraint: NSLayoutConstraint!
@IBOutlet weak var widthConstraint: NSLayoutConstraint!
var photo: UIImage! {
didSet {
// simulate networking delay
perform(#selector(setImageView), with: nil, afterDelay: Double.random(in: 0.2...1))
// setImageView()
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
@objc private func setImageView() {
let cellHeight = self.frame.height
let cellWidth = self.frame.width
let cellRatio = cellHeight / cellWidth
let photoRatio = photo.size.height / photo.size.width
var estimatedWidth = cellWidth
var estimatedHeight = cellHeight
if photoRatio > cellRatio {
estimatedWidth = cellWidth
estimatedHeight = cellWidth * photoRatio
} else {
estimatedHeight = cellHeight
estimatedWidth = cellHeight / photoRatio
}
widthConstraint.constant = estimatedWidth
heightConstraint.constant = estimatedHeight
imageView.image = photo
}
override func prepareForReuse() {
imageView.image = nil
}
}
You need to create new cell each time and assign the value to it. Although this is very dangerous thing to do and can cause your app to take so much memory over use your app will use more power and make the device slower.
Instead I suggest that you save your data into a Collection and to keep reusing it as you go.