简体   繁体   中英

How to add multiple rows in different multiple sections in tableview in swift

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM