【发布时间】: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,你能请也包括在内?
标签: ios swift uitableview