Problème de tableView

Bonjour à tous,
J’ai un petit souci de tableView. Dans mon projet, j’ai une tableView avec deux types de cellules (une pour le header et une “normale”). Mais, quand j’implémente une fonction prépare (sur la cellule header) pour un autre écran ou une fonction didselectrow, j’ai l’impression qu’il ne sait pas sur quelle cellule on clique (en gros, si je clique sur le header, il me sélectionne la cellule “normale” du dessous"). J’ai donc l’impression qu’il manque à un en endroit un bout de code pour lui dire quel type de cellule on est en train d’utiliser.

Si quelqu’un à une idée.
merci d’avance,

Benjamin

Intéressant comme sujet.
Je ne suis pas très doué mais je suppose que le soucis vient du fait qu’il ne sait pas que tu souhaites sélectionner une cellule de type header.

Pourrais t’on avoir un bout de code pour reproduire le bug ? (simple hein, pas besoin de l’app complete) :slight_smile:

oui bien sur.
alors pour la classe qui gère la customisation du header:

import UIKit

class TableViewHeader: UITableViewHeaderFooterView {

//Création des élements d’interface
@IBOutlet weak var Lbl_name: UILabel!
@IBOutlet weak var Lbl_amount: UILabel!

override func awakeFromNib() {
super.awakeFromNib()
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}

func DisplayUserName(user: Users) {
Lbl_name.text = user.name
Lbl_name.textColor = UIColor.white

}

func DisplayAmountDue(user: Users) {
Lbl_amount.text = String(user.GetUserAmount(index: user))
Lbl_amount.textColor = UIColor.white
}

et le bout de code de la table view dans le view controller
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell: TableViewHeader! = tableView.dequeueReusableHeaderFooterView(withIdentifier: “TableViewHeader”) as? TableViewHeader
if let user = _ordersManager.GetUser(index: section){
headerCell.DisplayUserName(user: user) // l’exception se produit ici !!!
headerCell.DisplayAmountDue(user: user)
}
}

Je ne sais pas si je t’apporte une solution qui conviendra, mais voila ce que j’ai fait.

La fonction de base pour savoir si on a cliqué sur une ligne est celle-ci :

override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    print(indexPath)
    
    return indexPath
}

Effectivement, quand on clic sur une cellule dite “normale”, on a un resultat du type

[0,1]

Et quand on clic sur une entete de section, on a un truc similaire.
L’idée est de faire un gestionnaire de clic a la main.

Dans ta méthode qui gère la cellule d’entete tu fait comme ca :

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    // tap
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleHeaderTap))
    
    tapGestureRecognizer.delegate = self
    tapGestureRecognizer.numberOfTapsRequired = 1
    tapGestureRecognizer.numberOfTouchesRequired = 1
    
    // cell
    
    let  headerCell = tableView.dequeueReusableCell(withIdentifier: "header") as! CustomHeaderCell

    headerCell.headerLabel?.text = continents[section].name
    headerCell.addGestureRecognizer(tapGestureRecognizer)

    return headerCell
}

Et plus loin dans le code tu as ta méthode a ajouter qui va gérer le clic :

@objc func handleHeaderTap(gestureRecognizer: UIGestureRecognizer)
{
    print("Tapped")
}

Très important, ne pas oublier d’implémenter la classe UIGestureRecognizerDelegate pour le delegate

Le code final fonctionnel :

import UIKit

class Continent {
    var name: String;
    
    init(name: String) {
        self.name = name;
    }
}

class Country {
    var continent: Continent;
    var name: String;
    
    init(name: String, continent: Continent) {
        self.continent = continent;
        self.name = name;
    }
}

class TableViewController: UITableViewController, UIGestureRecognizerDelegate {
    
    var continents: Array<Continent> = []
    var countries: Array<Country> = []

    override func viewDidLoad() {
        super.viewDidLoad()
        
        continents.append(Continent(name: "Europe"))
        continents.append(Continent(name: "Asie"))
        continents.append(Continent(name: "Amérique du sud"))
        
        countries.append(Country(name: "France", continent: continents[0]))
        countries.append(Country(name: "Espagne", continent: continents[0]))
        countries.append(Country(name: "Allemagne", continent: continents[0]))
        
        countries.append(Country(name: "Japon", continent: continents[1]))
        countries.append(Country(name: "Chine", continent: continents[1]))
        countries.append(Country(name: "Inde", continent: continents[1]))
        countries.append(Country(name: "Corée", continent: continents[1]))
        
        countries.append(Country(name: "Argentine", continent: continents[2]))
        countries.append(Country(name: "Brésil", continent: continents[2]))
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return continents.count;
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return countries.filter({ (country:Country) -> Bool in
            return country.continent === continents[section]
        }).count
    }
    
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        
        cell.textLabel?.text = countries[indexPath.row].name
        
        return cell
    }
    
    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        // tap
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleHeaderTap))
        
        tapGestureRecognizer.delegate = self
        tapGestureRecognizer.numberOfTapsRequired = 1
        tapGestureRecognizer.numberOfTouchesRequired = 1
        
        // cell
        
        let  headerCell = tableView.dequeueReusableCell(withIdentifier: "header") as! CustomHeaderCell

        headerCell.headerLabel?.text = continents[section].name
        headerCell.addGestureRecognizer(tapGestureRecognizer)

        return headerCell
    }

    //test 1
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        print(indexPath)
        
        return indexPath
    }
    
    //test 2

    @objc func handleHeaderTap(gestureRecognizer: UIGestureRecognizer)
    {
        print("Tapped")
    }
}

ok merci beaucoup. je vais regarder ça.

Bon tout marche bien. Merci bcp.
j’ai juste un dernier problème: si je tappe sur la section et que je veux à partir de là, passer des données à un second ViewController via une fonction prépare… ça ne marche pas.
En effet si on utilise un truc du style, dans un if let : sélectedIndex = self.tableView.indexPathForSelectedRow?.row(ou section), il ne trouve rien. J’imagine parce qu’en fait on fait un tap et pas un sélect de la cellule proprement dite…
Il doit surement avoir une autre fonction pour trouver le indexPath… Je fais des recherches mais je prends les conseils aussi :slight_smile:

Merci d’avance