I have tableview in that cell I have created header view in that header I have label and button, I am getting label values from array and that array counts number of sections which works fine. but when I tap on button I need to expand cell and in that expanded cell I need to add label but while I am tapping button it says
error: Index out of range
in numberOfRowsInSection
and it is not expanded.
here is my code:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, DataSendingDelegateProtocol, FieldsDelegateProtocol {
var shouldCellBeExpanded:Bool = false
var indexOfExpendedCell:NSInteger = -1
// let kHeaderSectionTag: Int = 6900;
@IBOutlet weak var tableView: UITableView!
var sectionArray = [String]()
var sectionItemsArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
//self.tableView!.tableFooterView = UIView()
}
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func sendDataToTableRow(myData: String) {
self.sectionItemsArray.append(myData)
tableView.reloadData()
// print(iteamsArray)
}
func sendDataToSectionLabel(myData: String) {
self.sectionArray.append(myData)
tableView.reloadData()
print(sectionArray)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "segue") {
let vc = segue.destination as! PopViewController
vc.delegate = self
}
else if (segue.identifier == "fieldsSegue") {
let vc = segue.destination as! FieldsViewController
vc.delegate = self
}
}
@objc func expandButnClicked(sender:UIButton){
print("expand button tapped")
shouldCellBeExpanded = !shouldCellBeExpanded
indexOfExpendedCell = sender.tag
if shouldCellBeExpanded {
self.tableView.beginUpdates()
self.tableView.endUpdates()
}
else {
self.tableView.beginUpdates()
self.tableView.endUpdates()
}
}
@IBAction func addBtn(_ sender: Any) {
}
// MARK: - Tableview Methods
func numberOfSections(in tableView: UITableView) -> Int {
return sectionArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.indexOfExpendedCell == section) {
let arrayOfItems = self.sectionItemsArray[section]
return arrayOfItems.count
} else {
return 0
}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if (self.sectionArray.count != 0) {
return self.sectionArray[section] as? String
}
return ""
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44.0;
}
/*func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat{
return 0;
}*/
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
header.contentView.backgroundColor = UIColor.colorWithHexString(hexStr: "#0075d4")
header.textLabel?.textColor = UIColor.white
let button = UIButton(frame: CGRect(x: 380, y: 10, width: 15, height: 15))
button.backgroundColor = UIColor.green
button.tag = section
button.addTarget(self, action: #selector(expandButnClicked), for: .touchUpInside)
header.addSubview(button)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if shouldCellBeExpanded && indexPath.row == indexOfExpendedCell {
return 200
}
else {
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! TableViewCell
cell.textLab?.textColor = UIColor.black
cell.textLab.text = sectionItemsArray[indexPath.row]
cell.backgroundColor = UIColor.black
return cell
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
Please help me in the code.
If section is expanded return sectionItemsArray array count in numberOfRowsInSection method
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.indexOfExpendedCell == section) {
return self.sectionItemsArray.count
} else {
return 0
}
}
Your problem may be pinpointed to 2 methods you implemented:
func numberOfSections(in tableView: UITableView) -> Int {
return sectionArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.indexOfExpendedCell == section) {
let arrayOfItems = self.sectionItemsArray[section]
return arrayOfItems.count
} else {
return 0
}
}
In the first one you explain how many sections you have for which you used sectionArray
but then in the second you use another array sectionItemsArray
. Your crash is most likely in case of sectionItemsArray[sectionArray.count-1]
which will fail when sectionItemsArray
has fewer number of elements than sectionArray
.
You should probably have this consistent and use only one array. In your case it makes sense to use array of arrays to represent sections and rows. But in general it might be better to use custom structures. Consider something like the following:
class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
class Section {
class Row {
let name: String
var shown: Bool = true
init(name: String) { self.name = name }
}
let name: String
var shown: Bool = true
var rows: [Row]
init(name: String, rows: [Row] = [Row]()) { self.name = name; self.rows = rows }
}
var sections: [Section]!
override func viewDidLoad() {
super.viewDidLoad()
sections = [
Section(name: "Empty"),
Section(name: "Second section", rows: [.init(name: "row 1"), .init(name: "row 2")]),
Section(name: "Third section", rows: [.init(name: "row 1"), .init(name: "row 2")])
]
}
func numberOfSections(in tableView: UITableView) -> Int {
return sections.filter { $0.shown }.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections.filter { $0.shown }[section].name
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections.filter { $0.shown }[section].rows.filter { $0.shown }.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let name: String = sections.filter { $0.shown }[indexPath.section].rows.filter { $0.shown }[indexPath.row].name
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
cell.textLabel?.text = name
return cell
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.