0

I have a custom xib file which contains a label and a UICollectionView. I have a second xib file for the collection view's cell with a custom subclass of UICollectionViewCell.

The parent xib file's owner looks like below-

import UIKit

class PackageSizePickerVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {


    @IBOutlet weak var collection: UICollectionView!


    let sizes: [PackageSize] = {
        let small = PackageSize(title: "Small", imageName: "S")
        let medium = PackageSize(title: "Medium", imageName: "M")
        let large = PackageSize(title: "Large", imageName: "L")
        let extralarge = PackageSize(title: "Extra Large", imageName: "XL")
        return [small, medium, large, extralarge]
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        collection.delegate = self
        collection.dataSource = self

        collection.register(UINib(nibName: "SizesCell", bundle: nil), forCellWithReuseIdentifier: "Sizecell") //register with nib

    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return sizes.count
    }

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


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if let cell = collection.dequeueReusableCell(withReuseIdentifier: "Sizecell", for: indexPath) as? SizesCell {
            let size = sizes[indexPath.row]
            cell.image = size.imageName
            cell.title = size.title
            return cell
        }else{
            return UICollectionViewCell()
        }
    }
}

enter image description here

The UICollectionViewCell xib file is named SizesCell.xib and the class file is SizesCell.swift, the code in SizesCell class looks like this-

import UIKit

class SizesCell: UICollectionViewCell {

    @IBOutlet weak var sizeImage: UIImageView!
    @IBOutlet weak var sizeLabel: UILabel!

    var image: String!
    var title: String!

    override init(frame: CGRect) {
        super.init(frame: frame)
        sizeImage.image = UIImage(named: image)
        sizeLabel.text = title
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

enter image description here enter image description here

enter image description here

Where PackageSize is a Struct as

struct PackageSize {
    let title: String
    let imageName: String
}

Now the problem I am facing is that the cells simply won't load into the collection view in the parent xib file and I simply can't figure out why the init in the UICollectionViewCell class is not being called at all. I have tried it with awakeFromNib() as well, but that didn't work either. The file owners, custom classes etc. are all set correctly in the IB. What am I missing here?

Anjan Biswas
  • 7,746
  • 5
  • 47
  • 77
  • Are you sure that your xib file called `SizesCell.xib`? – Vasilii Muravev Jul 10 '17 at 20:55
  • @VasiliiMuravev yep. See updated question with screenshot. – Anjan Biswas Jul 10 '17 at 20:57
  • Questions: is `cellForItemAt:` even called? Don't you call `reloadData()`? It should call `awakFromNib()` since you registered nib, not cell `initWithFrame()`. – Larme Jul 10 '17 at 21:03
  • @Larme I assume you meant `cellForItem`? and why would I need `reloadData()` here? My data is static and available at the time of initialization through `let sizes: [PackageSize]`. – Anjan Biswas Jul 10 '17 at 21:06
  • And there's no need to setup reusable identifier in xib file, cuz you're setting it up in `collection.register(UINib(nibName: "SizesCell", bundle: nil), forCellWithReuseIdentifier: "Sizecell")` – Vasilii Muravev Jul 10 '17 at 21:06
  • @VasiliiMuravev yes, I did remove that and tried, still no results. – Anjan Biswas Jul 10 '17 at 21:07
  • @Annjawn did you check that `cellForItemAt:` was called as @Larme suggested? Put breakpoint there or print something in log. – Vasilii Muravev Jul 10 '17 at 21:09
  • Yes I did notice that `cellForItemAt` is not called but I am not certain why. I just tried using reloadData() as `collection.reloadData()` in `viewDidLoad()` but still no results. – Anjan Biswas Jul 10 '17 at 21:10
  • @Annjawn that's mean that `sizes.count == 0` – Vasilii Muravev Jul 10 '17 at 21:12
  • How? You can see the array being initialized there and I can even print the contents of the array how can it be 0? I tried to hard code as `return 4` in `numberOfItemsInSection ` but still nothing happened. – Anjan Biswas Jul 10 '17 at 21:14
  • Is `sizeForItemAtIndexPath` called? If yes, try to divide the size by two (width & height) – Larme Jul 10 '17 at 21:22
  • `sizeForItemAt` is also not being called.. super weird. I have tried setting the `delegate` and `datasource` through IB and as well as code (as shown) in the question. But still didn't work. – Anjan Biswas Jul 10 '17 at 21:26
  • Is `func viewDidLoad()` called? Is `collectionView` nil? Are you sure you are using Swift 3 and not Swift 2? – Larme Jul 10 '17 at 21:54
  • 1
    Believe it or not, I just put a height constraint on the `CollectionView` and now it works. This is where I got the hint from - https://stackoverflow.com/a/30805456/1137672 .... Thanks Apple! – Anjan Biswas Jul 10 '17 at 21:56
  • Weird.......... – Vasilii Muravev Jul 10 '17 at 23:25
  • @annjawn : Sorry saw ur message now :) I believe u have ur problem solved :) Happy coding – Sandeep Bhandari Jul 11 '17 at 05:28
  • @SandeepBhandari yes. It was a weird issue but it's resolved. Thanks. – Anjan Biswas Jul 11 '17 at 05:29

0 Answers0