Hi Apple Dev Community,
I have a single ViewController, in which I have a (custom) CollectionView, in which I have 64 (custom) CollectionViewCells, each in which I have a single UILabel and UIImageView.
My goal is to populate the CollectionView with CollectionViewCells, with a common background image and a label (in this example, the label is simple the indexPath.item)
Straightfoward enough....
or you would think. I'm encountering weird behavior where only the first cell gets a label! To make matters worse, none of the cells are getting an image!
I figured the background color might be the culprint, so I commented the line out....and all of a sudden, the 8x8 grid turns into a 4x4 grid!
WHAT THE **** IS GOING ON!?? I've never seen any behavior like this....below is the code:
ViewController.swift
import UIKit
class ViewController: UIViewController{
var collectionView: collectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView = newCollectionView()
}
func newCollectionView() -> CollectionView {
let collectionView = CollectionView(viewController: self)
self.view.addSubview(collectionView)
collectionView.activateConstraints()
return collectionView
}
}
CollectionView.swift
import UIKit
class CollectionView: UICollectionView, UICollectionViewDelegate, UICollectionViewDataSource {
var viewController: ViewController!
init(viewController: ViewController) {
self.viewController = viewController
let width = viewController.view.frame.width - 20
let frame = CGRect(x: 0, y: (viewController.view.frame.height - width)/2, width: width, height: width)
let flowLayout = FlowLayout()
super.init(frame: frame, collectionViewLayout: flowLayout)
self.delegate = self
self.dataSource = self
self.register(CollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
self.backgroundColor = UIColor.red
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func activateConstraints() {
let view = viewController.view!
translatesAutoresizingMaskIntoConstraints = false
centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true widthAnchor.constraint(equalToConstant: view.bounds.width).isActive = true
heightAnchor.constraint(equalToConstant: view.bounds.width).isActive = true
contentInsetAdjustmentBehavior = .always
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 64
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! CollectionViewCell
cell.label.text = "\(indexPath.item)"
cell.backgroundColor = UIColor.gray // Comment this line out and the 8x8 grid turns into a 4x4 grid!
return cell
}
}
FlowLayout.swift
import UIKit
class FlowLayout: UICollectionViewFlowLayout {
var gridSize: Int = 8
override init() {
super.init()
self.minimumInteritemSpacing = 1
self.minimumLineSpacing = 1
self.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 0, right: 10)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func prepare() {
super.prepare()
// Make sure the collection view is valid
guard let collectionView = collectionView else { return }
let marginsAndInsets = sectionInset.left + sectionInset.right + collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right + minimumInteritemSpacing * CGFloat(gridSize - 1)
// Make item width as large as possible without bleeding
let cellSize = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(gridSize)).rounded(.down)
itemSize = CGSize(width: cellSize, height: cellSize)
}
override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext {
let context = super.invalidationContext(forBoundsChange: newBounds) as! UICollectionViewFlowLayoutInvalidationContext
context.invalidateFlowLayoutDelegateMetrics = newBounds.size != collectionView?.bounds.size
return context
}
}