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

时间:2017-08-24 17:14:34

标签: ios swift uicollectionview

我一直在试图找出此代码中的问题,因为它会使索引超出范围错误。但是,我无法理解问题所在。

这是代码

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
    }

}

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

Debugger screenshot

2 个答案:

答案 0 :(得分:1)

在override func collectionView(_ collectionView:UICollectionView,cellForItemAt indexPath:IndexPath) - &gt; UICollectionViewCell 不应该这条线

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

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

答案 1 :(得分:0)

我建议使用guard来确保您的商品可以像这样

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

}