CollectionView致命错误:索引超出范围

时间:2021-07-23 16:42:16

I've been trying to figure out what the issue is in this code for it to throw an index out of range error. However, I am unable to understand where the issue is.

我一直试图弄清楚这个代码中的问题是什么,它会使索引超出范围错误。但是,我无法理解问题所在。

Here is the code

这是代码

import UIKit
import Alamofire

class MenuViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    let cellId = "cellId"
    let headerId = "headerId"

    var itemCategories: [MenuItemCategory]?
    var menuItem: [MenuItem]?

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView?.backgroundColor = .white
        navigationItem.titleView = UIImageView(image: #imageLiteral(resourceName: "mooyahLabelLogo"))

        collectionView?.register(MenuViewControllerCell.self, forCellWithReuseIdentifier: cellId)
        collectionView?.register(MenuViewControllerHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerId)

        MenuItemCategory.fetchMenuItems { (itemCategories) in
            self.itemCategories = itemCategories
            self.collectionView?.reloadData()
        }

    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {

        if let count = itemCategories?.count {
            print("Number of Sections: \(count)")
            return count
        }
        return 0
    }


    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as! MenuViewControllerHeader

        if let categoryName = itemCategories?[indexPath.section].name {
            header.categoryNameLabel.text = categoryName
        }

        return header
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {

        return CGSize(width: view.frame.width, height: 44)

    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        if let count = itemCategories?[section].items?.count {
            print("Number of Items in Section: \(count)")
            return count
        }
        return 0
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MenuViewControllerCell

        if let category = itemCategories?[indexPath.item] {
            print("Section: \(category.name!)")
            if let itemsCount = category.items?.count {

                for i in 0..<itemsCount {
                    print("Item: \(category.items?[i].name ?? "")")
                    cell.itemNameLabel.text = category.items?[i].name ?? ""
                    cell.itemDescriptionLabel.text = category.items?[i].desc ?? ""

                    if let price = category.items?[i].price {
                        cell.itemPriceLabel.text = "AED \(price)"
                    }

                }

            }

        }

        return cell

    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        return CGSize(width: view.frame.width, height: 85)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

}

Here is the debugger print where it shows that my number of sections are correct as well as the number of items in section is correct. I am not sure where the issue arises from?

这是调试器打印,其中显示我的部分数量正确以及部分中的项目数是正确的。我不确定问题出在哪里?

Debugger screenshot

调试器截图

2 个解决方案

#1


1  

In override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell Shouldn't this line be

在override func collectionView(_ collectionView:UICollectionView,cellForItemAt indexPath:IndexPath) - > UICollectionViewCell这行不应该是

if let category = itemCategories?[indexPath.section] { .... }

Not

if let category = itemCategories?[indexPath.item] { .... }

#2


0  

I would suggest to use a guard to make sure that your items are available like this

我建议使用警卫来确保你的物品可以这样使用

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MenuViewControllerCell

guard let itemCategories = itemCategories, itemCategories.indices.contains(indexPath.item), let items = category.items else {
    return cell
}
if let category = itemCategories[indexPath.item] {
    print("Section: \(category.name!)")

    if let itemsCount = items.count {

        for i in 0..<itemsCount {
            if items.indices.contains(i) {
                print("Item: \(items[i].name ?? "")")
                cell.itemNameLabel.text = items[i].name ?? ""
                cell.itemDescriptionLabel.text = items[i].desc ?? ""

                if let price = category.items?[i].price {
                    cell.itemPriceLabel.text = "AED \(price)"
                }

            }
        }

    }

}

return cell

}

#1


1  

In override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell Shouldn't this line be

在override func collectionView(_ collectionView:UICollectionView,cellForItemAt indexPath:IndexPath) - > UICollectionViewCell这行不应该是

if let category = itemCategories?[indexPath.section] { .... }

Not

if let category = itemCategories?[indexPath.item] { .... }

#2


0  

I would suggest to use a guard to make sure that your items are available like this

我建议使用警卫来确保你的物品可以这样使用

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MenuViewControllerCell

guard let itemCategories = itemCategories, itemCategories.indices.contains(indexPath.item), let items = category.items else {
    return cell
}
if let category = itemCategories[indexPath.item] {
    print("Section: \(category.name!)")

    if let itemsCount = items.count {

        for i in 0..<itemsCount {
            if items.indices.contains(i) {
                print("Item: \(items[i].name ?? "")")
                cell.itemNameLabel.text = items[i].name ?? ""
                cell.itemDescriptionLabel.text = items[i].desc ?? ""

                if let price = category.items?[i].price {
                    cell.itemPriceLabel.text = "AED \(price)"
                }

            }
        }

    }

}

return cell

}