致命错误:numberOfRowsInSection 中的索引超出范围

Posted

技术标签:

【中文标题】致命错误:numberOfRowsInSection 中的索引超出范围【英文标题】:fatal error: Index out range in numberOfRowsInSection 【发布时间】:2017-08-15 08:33:14 【问题描述】:

我正在尝试使用 tableview 创建可折叠菜单。调用 return self.sideBars[section].movies!.count 时,函数 numberOfRowsInSection 出现错误。我没有得到的是,当我选择配置文件(其中一个选项卡)return self.sideBars[section].movies!.count 时,它会完美运行并显示数组。但是当我选择设置或选项(其他选项卡)时,我收到错误索引超出范围。我不确定为什么会这样。我已经尝试对设置和选项选项卡使用不同的数组,但我仍然让索引超出范围。帮助将不胜感激!提前致谢

这是发生错误的地方

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> (Int) 
    let it = String(describing: items[section])
    var item = items[section]

    guard item.isCollapsible else 
        if (it == "ProfileViewModelAboutItem") 
            return self.sideBars[section].movies!.count
        
        if (it == "ProfileViewModelsettingsItem") 
          return self.sideBars[section].movies!.count

        
        if (it == "ProfileViewModelOptionsItem") 
            return self.sideBars[section].movies!.count                
        
        return item.rowCount
    
    if item.isCollapsed 
        return 0
     else     
        if (it == "ProfileViewModelAboutItem") 
            return self.sideBars[section].movies!.count // This works fine
        
        if (it == "ProfileViewModelsettingsItem") 
              return self.sideBars[section].movies!.count // This is where error occurs: Index out of range
        
        if (it == "ProfileViewModelOptionsItem") 
            return self.sideBars[section].movies!.count // Also here, fatal error: Index out of range
        
        return item.rowCount
    

下面的整个代码以获得更多的理解

import Foundation

enum ProfileViewModelItemType 
    case profile
    case settings
    case options


protocol ProfileViewModelItem 
    var type: ProfileViewModelItemType  get 
    var sectionTitle: String  get 
    var rowCount:(Int)  get 
    var isCollapsible: Bool  get 
    var isCollapsed: Bool  get set 


extension ProfileViewModelItem 
    var rowCount: Int 
        return 1
    

    var isCollapsible: Bool 
        return true
    


class ProfileViewModel: NSObject 
    var items = [ProfileViewModelItem]()
    var sideBars = [sideBar]()
    var reloadSections: ((_ section: Int) -> Void)?

    override init() 
        super.init()

            let profile = sideBar(movies: [“Followers”, “Following”, “bye”], count: [“1”,”2”,“3”])
            let profileItems = ProfileViewModelAboutItem(sideBars: [profile])
            self.items.append(profileItems)

            let about = sideBar(movies: ["Delete Account", “test”], count: [“1”,”2”])
            let settingItem = ProfileViewModelsettingsItem(sideBars: [about])
            self.items.append(settingItem)

            let option = sideBar(movies: ["about", "FAQ"], count: [“1”,”2”])
            let optionsItem = ProfileViewModelOptionsItem(sideBars: [option])
            self.items.append(optionsItem)
    


extension ProfileViewModel: UITableViewDataSource 
    func numberOfSections(in tableView: UITableView) -> (Int) 
        return items.count
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> (Int) 
        let it = String(describing: items[section])
        var item = items[section]

        guard item.isCollapsible else 
            if (it == "ProfileViewModelAboutItem") 
                return self.sideBars[section].movies!.count
            
            if (it == "ProfileViewModelsettingsItem") 
                return self.sideBars[section].movies!.count
            
            if (it == "ProfileViewModelOptionsItem") 
                return self.sideBars[section].movies!.count                
            
            return item.rowCount
        
        if item.isCollapsed 
            return 0
         else 
            if (it == "ProfileViewModelAboutItem") 
                return self.sideBars[section].movies!.count // This works fine
            
            if (it == "ProfileViewModelsettingsItem") 
                return self.sideBars[section].movies!.count // This is where error occurs: Index out of range
               
            if (it == "ProfileViewModelOptionsItem") 
                return self.sideBars[section].movies!.count // Also here, fatal error: Index out of range
               
            return item.rowCount
        
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let item = items[indexPath.section]
        switch item.type 
        case .profile:
            if let item = item as? ProfileViewModelAboutItem, let cell = tableView.dequeueReusableCell(withIdentifier: myProfileCell.identifier, for: indexPath) as? myProfileCell             
               let title = item.sideBars[indexPath.section].movies[indexPath.row]
                cell.profileLabel.text = title
                return cell
               
        case .settings:
            if let item = item as? ProfileViewModelsettingsItem, let cell = tableView.dequeueReusableCell(withIdentifier: settingsCell.identifier, for: indexPath) as? settingsCell 
              let title = item.sideBars[indexPath.section].movies[indexPath.row]
                cell.settingsLabel.text = title
                return cell
             
        case .options:
            if let item = item as? ProfileViewModelOptionsItem, let cell = tableView.dequeueReusableCell(withIdentifier: optionsCell.identifier, for: indexPath) as? optionsCell             
                let title = item.sideBars[indexPath.section].movies[indexPath.row]
                cell.optionLabel.text = title        
                return cell
            
        
        return UITableViewCell()
    


extension ProfileViewModel: UITableViewDelegate 
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? 
        if let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: HeaderView.identifier) as? HeaderView 
            let item = items[section]

            headerView.item = item
            headerView.section = section
            headerView.delegate = self
            return headerView
        
        return UIView()
    


extension ProfileViewModel: HeaderViewDelegate 
    func toggleSection(header: HeaderView, section: Int) 
        var item = items[section]
        if item.isCollapsible 

            // Toggle collapse
            let collapsed = !item.isCollapsed
            item.isCollapsed = collapsed
            header.setCollapsed(collapsed: collapsed)


            reloadSections?(section)
        
    


class ProfileViewModelAboutItem: ProfileViewModelItem 

    var type: ProfileViewModelItemType 
        return .profile
    

    var sectionTitle: String 
        return "My Profile"
    

    var isCollapsed = true

    var sideBars = [sideBar]()

         var rowCount: Int 
        return self.sideBars.count
    

    init(sideBars: [sideBar]) 
        self.sideBars = sideBars
    



class ProfileViewModelsettingsItem: ProfileViewModelItem 

    var type: ProfileViewModelItemType 
        return .settings
    

    var sectionTitle: String 
        return "Settings"
    

    var isCollapsed = true


   var sideBars = [sideBar]()


    var rowCount: Int 
        return self.sideBars.count
    

    init(sideBars: [sideBar]) 
        self.sideBars = sideBars
    



    class ProfileViewModelOptionsItem: ProfileViewModelItem 

        var type: ProfileViewModelItemType 
            return .options
        

        var sectionTitle: String 
            return “Options”
        

        var isCollapsed = true

        var sideBars = [sideBar]()

        var rowCount: Int 
            return self.sideBars.count
        

        init(sideBars: [sideBar]) 
            self.sideBars = sideBars
            

侧边栏结构

struct sideBar 

    var movies: [String]
    var count: [String]
   init(movies: [String], count: [String])
        self.movies = movies
        self.count = count        
    

【问题讨论】:

只发布解释问题的代码。这太过分了。请删除所有这些空行。 每次我发布一个问题时,我总是被要求发布更多代码,所以这就是我这样发布它的原因。我已将其更新为更具体的错误发生位置@meaning-matters 尝试在“麻烦”块中放置一个断点,看看数组sideBars是否有索引section。如果没有,您的填充和/或访问sideBars的逻辑有问题 我添加了一个断点来查看 sideBars 是否有索引部分,但我再次收到错误索引超出范围。所以我对sideBars @Malik的逻辑一定有问题 可能是因为你发布了大量代码,所以很难全部看完,但我找不到你的代码部分,你实际上用数据填充sideBars,你能请也包括在内? 【参考方案1】:

问题是您只填充了子类的sideBars 数组。 ProfileViewModel 类的 sideBars 数组永远不会填充数据,因为您只会在子类的初始化程序中改变数组。但是,您在填充数据时使用超类的sideBars,这是一个空数组。

override init() 
    super.init()

    let profile = sideBar(movies: [“Followers”, “Following”, “bye”], count: [“1”,”2”,“3”])
    let profileItems = ProfileViewModelAboutItem(settings: [profile])
    self.items.append(profileItems)
    self.sideBars.append(profile)    

    let about = sideBar(movies: ["Delete Account", “test”], count: [“1”,”2”])
    let settingItem = ProfileViewModelsettingsItem(sideBars: [about])
    self.items.append(settingItem)
    self.sideBars.append(about)

    let option = sideBar(movies: ["about", "FAQ"], count: [“1”,”2”])
    let optionsItem = ProfileViewModelOptionsItem(sideBars: [option])
    self.items.append(optionsItem)
    self.sideBars.append(option)

一些一般建议:请遵循Swift 命名约定,即以大写字母开头类型名称,例如struct SideBar,并为变量名称使用小写驼峰命名,例如var sideBars = [SideBar]()。如果我是你,我也会重组我的整个模型,这似乎过于复杂了。

【讨论】:

非常感谢您的回复。我想我必须找到另一种方法来实现我想要实现的目标。大部分代码来自我遵循的示例。 不用担心。如果您觉得我的回答有用,请考虑接受。 只是重新阅读您的评论,您能否提出一种填充 ProfileViewModel 的侧边栏数组的方法? 好的,所以现在我不再收到 numberOfRowsInSection 中的错误,这很好,但现在同样的错误出现在 line item.sideBars[indexPath.section].movi​​es[indexPath.row] 上的 cellForRowAt 中跨度> 好的,我已经成功了。我删除了“项目”,所以我使用了 sideBars[indexPath.section].movi​​es[indexPath.row] 而不是 item.sideBars[indexPath.section].movi​​es[indexPath.row] 并且它有效!非常感谢大家的帮助【参考方案2】:

一个非常简单的调试技术是:

代替:

return self.sideBars[section].movies!.count

使用:

let tempSideBarsCount = self.sideBars.count

它将帮助您了解数据和单元格之间是否存在错位。

【讨论】:

以上是关于致命错误:numberOfRowsInSection 中的索引超出范围的主要内容,如果未能解决你的问题,请参考以下文章

C# 中连接SQLServer 出现内部致命错误

使命召唤14致命错误怎么解决?

打开AutoCAD 文件就会弹出致命错误

重命名应用程序包生成致命错误“执行重构时发生致命错误”

天正总出现致命错误?是怎么回事儿?

游戏更新就出现发生致命错误Win32Error怎么回事