Regarding TableViews: How can I manage section titles and rows through classes?

So I have been studying Swift and trying to use a TableView with two sections. The thing is: I have successfully developed an application using TableViewController with just one section and used data from a class called "Opcao" to populate the rows.

So I decided to create another section by setting return 2 on override func numberOfSections(in tableView: UITableView) -> Int and it worked, I only really needed two sections.

My problem: both of the sections are presenting the same number of rows and the same content on it. How could I change it? I mean, I would like the second section called "Teste" to have its own cell fields (different from the first section) but also populated with info of Opcao class.

The sections names on my TableView should be actually the attribute called "section", and the rows content should be the the number of rows in a cell is how many objects there are with which kind of "section". What should I do?

Opcao.swift:

class Opcao {
var nome:String
var descricao: String
var section: String
var segueIdentifier: String


init(nome: String, descricao: String, section: String, segueIdentifier: String){
    self.nome = nome //displayed as main value of the cell
    self.descricao = descricao //description which goes bellow the cell title
    self.section = section // what I though it could be the section tittle which the option belongs to
    self.segueIdentifier = segueIdentifier //used for other stuff, not relevant to this situation

}

Parts of TableViewController.swift:

class TableViewController: UITableViewController {

var opcoes: [Opcao] = []
var titulos: [String] = ["1a Habilitação", "Teste"]


override func viewDidLoad() {
    super.viewDidLoad()

    gerarOpcoes()
}




func gerarOpcoes(){


    //criando opcao 1
    var opcao1: Opcao
    opcao1 = Opcao(nome: "Novo simulado", descricao: "Clique para começar um novo simulado.", section: "phab", segueIdentifier: "A")
    self.opcoes.append(opcao1)


    //criando opcao 2
    var opcao2: Opcao
    opcao2 = Opcao(nome: "Responder livremente", descricao: "Responda diversas perguntas sem tempo limite.", section: "phab", segueIdentifier: "B")
    self.opcoes.append(opcao2)


    //criando opcao 3
    var opcao3: Opcao
    opcao3 = Opcao(nome: "Histórico", descricao: "Veja seus últimos resultados.", section: "phab", segueIdentifier: "C")
    self.opcoes.append(opcao3)

}
// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 2
}


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return opcoes.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = self.tableView.dequeueReusableCell(withIdentifier: "celula", for: indexPath)
    cell.textLabel?.text = self.opcoes[indexPath.row].nome
    cell.detailTextLabel?.text = self.opcoes[indexPath.row].descricao

    return cell
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return titulos[section]
}

Upvotes: 0

Views: 42

Answers (2)

emrepun
emrepun

Reputation: 2666

You can do it in a variety of ways. Easiest way would be having different arrays for different sections (Although it might not be the best approach). Then altering numberofRowsInSection depending on that too. Lets see:

Create another array:

var opcoesSecond: [Opcao] = []

Another deployment method for second array, this time lets put two objects only:

func gerarOpcoesForSecond(){
    var opcao1: Opcao
    opcao1 = Opcao(nome: "Novo simulado", descricao: "Clique para começar um novo simulado.", section: "phab", segueIdentifier: "A")
    self.opcoesSecond.append(opcao1)

    //criando opcao 2
    var opcao2: Opcao
    opcao2 = Opcao(nome: "Responder livremente", descricao: "Responda diversas perguntas sem tempo limite.", section: "phab", segueIdentifier: "B")
    self.opcoesSecond.append(opcao2)
}

Call both array deployment methods in viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    gerarOpcoes()
    gerarOpcoesForSecond()
}

Then in your numberofRowsInSection method:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
        return opcoes.count        
    } else {
        return opcoesSecond.count
    }
}

In your cellForRowAt method:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "celula", for: indexPath)

    if indexPath.section == 0 {
        cell.textLabel?.text = self.opcoes[indexPath.row].nome
        cell.detailTextLabel?.text = self.opcoes[indexPath.row].descricao
    } else {
        cell.textLabel?.text = self.opcoesSecond[indexPath.row].nome
        cell.detailTextLabel?.text = self.opcoesSecond[indexPath.row].descricao
    }
    return cell
}

Again as mentioned in the comments, two-dimensional array might be better to prevent code repetition like we have in cellForRowAt method.

But this should solve your problem.

Upvotes: 1

bitma
bitma

Reputation: 137

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return opcoes.count
}

you should return count based on the section.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = self.tableView.dequeueReusableCell(withIdentifier: "celula", for: indexPath)
    cell.textLabel?.text = self.opcoes[indexPath.row].nome
    cell.detailTextLabel?.text = self.opcoes[indexPath.row].descricao

    return cell
}

again, you should set cell based on the section.

Upvotes: 0

Related Questions