Why is collection view cell not in the right class?

Hi


I have a UICollectionView. I have set the class to be PortfolioCollectionViewCell, which Xcode finds an puts in, but when I ask the class:

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) /

print("class =", String(describing: type(of: cell)))

it tells me class = UICollectionViewCell


I had tried to move Main.storyboard to the top of Project Navigator, but it disappeared and I drag-dropped it back into the project, and had to set the TargetMembership. I deleted and recreated this collection view cell. But it is ignoring the class type I have set.


What could be the cause of this? (XCode Version 9.0 beta 3 9M174d)


---
Mark

Replies

You should write :


let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PortfolioCollectionViewCell

Thanks, but I had been doing that. That gave me this error:
Could not cast value of type 'UICollectionViewCell' (0x10b2a36d8) to 'BusinessApplication.PortfolioCollectionViewCell

Can you show how you defined BusinessApplication.PortfolioCollectionViewCell and collectionView


Please also post the collectionView func where you dequeue.


You should have something like :

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
     guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier(identifier: "CollectionViewCellID">, forIndexPath: NSIndexPath>) as? PortfolioCollectionViewCell else {
         return UICollectionViewCell()
         }

The error message shows that the actual cell dequeued with `dequeueReusableCell(withReuseIdentifier:for:)` is of type `UICollectionViewCell`,

so, it cannot be converrted to your `PortfolioCollectionViewCell`.


Which means the class of the cell is not well setup for the cell with the `reuseIdentifier`.


Please check these things:

  • Check the class setting of the cell in your storyboard.
  • Confirm your `PortfolioCollectionViewCell` actually a subclass of `UICollectionViewCell`. (Not `UITableViewCell`, is it OK?)
  • Are you using the right `reuseIdentifier`?

Thanks for your replies.


This is the code that is thowing the "Could not cast" error. There is only one cell in storyboard.

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PortfolioCollectionViewCell
        print("class =", String(describing: type(of: cell)))
        cell.cellImageView.image = UIImage(named: imageList[indexPath.item])

        return cell
    }



The resuse identifier is declared thusly:

private let reuseIdentifier = "portfolioCell"


Copying and pasting from Collection resuable view: Identifier:
portfolioCell


Copying and pasting from the Custom Class of the cell:

PortfolioCollectionViewCell, where "inherit module from target" is checked.

The declaration of that class is:

class PortfolioCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var cellImageView: UIImageView!
}



Everything seems to be correct, and it was working (iirc) before my little mishap with Main.storyboard. I suspect that there may be some namespace issue going on. I have completely deleted and reconstructed that UICollectionViewController but I am getting the same error.


I just did some more debugging. I changed the cell For Item function to this:

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
        print("class =", String(describing: type(of: cell)))
        print("cell.reuseIdentifier =", cell.reuseIdentifier ?? "No identifier")
        if reuseIdentifier != cell.reuseIdentifier {
            print("reuseidentifiers not equal")
        }
        return cell
    }


and got this:

class = UICollectionViewCell

cell.reuseIdentifier = portfolioCell

class = UICollectionViewCell

cell.reuseIdentifier = portfolioCell

class = UICollectionViewCell

cell.reuseIdentifier = portfolioCell

So the identifiers match, but the assigned class is not being picked up.


This is a bit strange! Any ideas?


---

Mark

I can create any number of CollectionView apps and all of them work as expected with the same version of Xcode.


So, please try with a freshly made new project. You can copy Swift source files from your issuing project, but do not copy any parts of the Main.storyboard.

(Of course, you should not move the Main.storyboard to the top!)

Is there some extra knowedge behind your advice "Of course, you should not move the Main.storyboard to the top!" ?

Probably you did it already : try a clean build forlder.

In my experience, when moving or copying some files shown in the Project Navigator by drag-n-drop, some of the contents shown in the editor field was not the contents of the files of the project, and I was editing the copy source in another project. I'm sure I have checked Copy Items If Needed. (Although the copied files were not storyboard files.) Moving files may cause unexpected behavior in Xcode 9, surely it's a beta.

(I just have remembered, not only by drag-n-drop, but Add Files... has also shown an odd behavior as above.)

I would probably go to those lengths if this were an important project, but it's just a tutorial. I would rather work out what the problem is. The storyboard is already quite complex and would take a while to re-do.

I have started poking round in the text of the storyboard and other files in the project to see if I can identify some difference, but I am in unfamiliar territory.

If you have something like this in your code:

// Register cell classes
self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)


replace the type of the cell for your own custom cell type. Like so:

// Register cell classes
self.collectionView!.register(MyCell.self, forCellWithReuseIdentifier: reuseIdentifier)


Wherever you dequeue your cell, you will no longer need to cast it to your custom type.

You diid not understand what I proposed.


Clean Build Folder is a command to reset the build links which may cause problems because inconsistent; it does not erase anything in your storyboard. You call it in Project Menu.

choose the reusable view's xib file and make sure you input correct custom class name

xib file --- identity inspector ---- custom class