Search code examples
iosswiftuitableviewtableviewsections

How to add another section (button) after some data in table view swift?


I'm trying to create a number of section based on user input. I'm able to do that, but the next step is to create button at the end of the section. However, we do not know what's the last section since it's up to the user request. It looks like this:

enter image description here

Now, I have created another cell for the button like so:

enter image description here

Here's my code so far:

var numberOfSection: Int = 0 {
    didSet {
        tableView.reloadData()
    }
}

override func numberOfSections(in tableView: UITableView) -> Int {
    if numberOfSection == 0 {
        return 2
    }
    else if numberOfSection <= numberOfSection {
        return numberOfSection + 1
    }
    return numberOfSection + 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
        return 1
    }
    else if section <= numberOfSection + 1 {
        for _ in 0...numberOfSection {
            return testeSpec.count
        }
    }
    else {
        return 1
    }
    return 1
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let tableSection = indexPath.section
    if tableSection == 0 {
        let cells = tableView.dequeueReusableCell(withIdentifier: "serverNumbCell", for: indexPath) as! CellOutlet
        let txtFieldServerNumber = cells.txtFieldServerNumb
        cells.lblSectionNumb.text = "Number of section:"
        txtFieldServerNumber?.addTarget(self, action: #selector(sectionTxtFieldDidChange), for: .editingChanged)
        return cells
    }
    
    else if tableSection <= numberOfSection + 1 {
        for _ in 0...numberOfSection {
            let cells = tableView.dequeueReusableCell(withIdentifier: "serverSpecCell", for: indexPath) as! CellOutlet
            let specWS = testSpec[indexPath.row]
            cells.labels.text = specWS.spec
            return cells
        }
    }
    else {
        let cells = tableView.dequeueReusableCell(withIdentifier: "buttonCell", for: indexPath) as! CellOutlet
        cells.btnResult.setTitle("OK", for: .normal)
        return cells
    }
    return CellOutlet()
}

I have another class hooked up with all the outles. How can I create that another button in a section after all those unknown number of sections?

Thankyou in advance


Solution

  • Dynamic number of sections

    In ViewController class

    class ViewController: UIViewController {
        
        var numberOfSections: Int = 0
        @IBOutlet weak var tableView: UITableView!
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.dataSource = self
            tableView.delegate = self
        }
    }
    extension ViewController: UITableViewDelegate, UITableViewDataSource {
        func numberOfSections(in tableView: UITableView) -> Int {
            return numberOfSections + 1
        }
        
        func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
            "section"
        }
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            if section == 0 {
                return 1
            } else if numberOfSections > section {
                return 2
            } else {
                return 1
            }
        }
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            
            if indexPath.section == 0 {
                guard let cell = tableView.dequeueReusableCell(withIdentifier: "ServerSpecCell") as? ServerSpecCell else {return UITableViewCell()}
                
                cell.titleLabel.text = "Number of section"
                cell.numberOfSectionAction = { userInput in
                    self.numberOfSections = userInput
                    self.tableView.reloadData()
                }
                return cell
            }
            
            if numberOfSections > indexPath.section {
                guard let cell = tableView.dequeueReusableCell(withIdentifier: "ServerSpecCell") as? ServerSpecCell else {return UITableViewCell()}
                return cell
            }
            
            guard let cell = tableView.dequeueReusableCell(withIdentifier: "ButtonCell") as? ButtonCell else {return UITableViewCell()}
            return cell
        }
    }
    
    
    class ButtonCell: UITableViewCell {
        
        
        override class func awakeFromNib() {
            super.awakeFromNib()
            
        }
    }
    

    In UITableViewCell subclass

    class ServerSpecCell: UITableViewCell, UITextFieldDelegate {
    
        @IBOutlet weak var titleLabel: UILabel!
        @IBOutlet weak var serverTextField: UITextField!
        
        var numberOfSectionAction: ((Int)->Void)?
        
        override func awakeFromNib() {
            super.awakeFromNib()
            serverTextField.delegate = self
        }
    
        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
    
            // Configure the view for the selected state
        }
        
        func textFieldDidChangeSelection(_ textField: UITextField) {
            guard let sections = Int(textField.text ?? "0") else { return }
            numberOfSectionAction?(sections+1)
        }
    
    }