iosswiftuicollectionviewuicollectionviewcelluicollectionviewflowlayout

Swift: UICollectionView sizeForItemAt will never be executed


I'm making a CollectionView which has 2 sections, everything is fine but the size. I'd like to give different size of cell in different section, but when I call sizeForItemAt, Xcode shows a yellow warning "Will never be executed". Here's how I set my CollectionView functions:

extension ArtistProfileViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

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

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    switch mySections[section] {
    case .profile:
        return 1
    case .relatedArtists:
        return 10
    }
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    switch mySections[indexPath.section] {
    case .profile:
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ArtistProfileCell.identifier, for: indexPath) as? ArtistProfileCell else { return UICollectionViewCell()}
        
        return cell
    case .relatedArtists:
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RelatedArtistCell.identifier, for: indexPath) as? RelatedArtistCell else { return UICollectionViewCell()}
        cell.myImageView.image = UIImage(systemName: "person")
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
          return CGSize(width: 100, height: 100)
       }
}

And here is how I set my CollectionView:

    var myCollectionView: UICollectionView = {
    
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical
    layout.estimatedItemSize = .zero
    
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.register(ArtistProfileCell.self, forCellWithReuseIdentifier: ArtistProfileCell.identifier)
    cv.register(RelatedArtistCell.self, forCellWithReuseIdentifier: RelatedArtistCell.identifier)
    
    return cv
}()

I did set the CollectionView.delegate/datasource to self in viewDidLoad, and I can see the cell appear on the screen. However, the size of cell does not change at all. Plus, I know one of the solution is to set the estimated size to none in storyboard, but I don't know how to set it programmatically. So I don't know if it works.

There's one thing odd, when I call sizeForItemAt, it does not show the complete function automatically. I have to type it by myself like this.

Does anyone can help? Thanks in advance!


Solution

  • You put sizeForItemAt inside cellForItemAt. They need to be separate.

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        switch mySections[indexPath.section] {
        case .profile:
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ArtistProfileCell.identifier, for: indexPath) as? ArtistProfileCell else { return UICollectionViewCell()}
            
            return cell
        case .relatedArtists:
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RelatedArtistCell.identifier, for: indexPath) as? RelatedArtistCell else { return UICollectionViewCell()}
            cell.myImageView.image = UIImage(systemName: "person")
            return cell
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 100, height: 100)
    }
    

    Try selecting your code, then pressing Ctrl + i to re-format your code (fixes indenting too!)