致命错误: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].movies[indexPath.row] 上的 cellForRowAt 中跨度> 好的,我已经成功了。我删除了“项目”,所以我使用了 sideBars[indexPath.section].movies[indexPath.row] 而不是 item.sideBars[indexPath.section].movies[indexPath.row] 并且它有效!非常感谢大家的帮助【参考方案2】:一个非常简单的调试技术是:
代替:
return self.sideBars[section].movies!.count
使用:
let tempSideBarsCount = self.sideBars.count
它将帮助您了解数据和单元格之间是否存在错位。
【讨论】:
以上是关于致命错误:numberOfRowsInSection 中的索引超出范围的主要内容,如果未能解决你的问题,请参考以下文章