ios - fatal error: Index out range in numberOfRowsInSection -
i trying create collapsible menu using tableview. getting error in func numberofrowsinsection when return self.sidebars[section].movies!.count called. thing don't when select profile(one of tabs) return self.sidebars[section].movies!.count called , works , displays array. when select settings or options (the other tabs) error index out of range. i'm not sure why happening. i've tried using different arrays settings , options tabs still index out of range. appreciated! in advance
this error occurs
func tableview(_ tableview: uitableview, numberofrowsinsection section: int) -> (int) { let = 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 // works fine } if (it == "profileviewmodelsettingsitem") { return self.sidebars[section].movies!.count // error occurs: index out of range } if (it == "profileviewmodeloptionsitem") { return self.sidebars[section].movies!.count // here, fatal error: index out of range } return item.rowcount } } the whole code below more of understanding
import foundation enum profileviewmodelitemtype { case profile case settings case options } protocol profileviewmodelitem { var type: profileviewmodelitemtype { } var sectiontitle: string { } var rowcount:(int) { } var iscollapsible: bool { } var iscollapsed: bool { 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 = 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 = 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 // works fine } if (it == "profileviewmodelsettingsitem") { return self.sidebars[section].movies!.count // error occurs: index out of range } if (it == "profileviewmodeloptionsitem") { return self.sidebars[section].movies!.count // 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 } } sidebar struct
struct sidebar { var movies: [string] var count: [string] init(movies: [string], count: [string]){ self.movies = movies self.count = count } }
the problem populate sidebars array of subclasses. sidebars array of profileviewmodel class never populated data, since ever mutate array inside initializer of subclasses. however, use sidebars of superclass when populating data, empty array.
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 = 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) } some general advice: please follow swift naming convention, start type names uppercase letter, such struct sidebar , use lowercase camelcase naming variable names, such var sidebars = [sidebar](). if you, restructure whole model, seems way overcomplicated.
Comments
Post a Comment