UITableview avec plus d'une cellule personnalisée avec Swift

111

Je souhaite utiliser un UITableview avec différentes tablesViewCells personnalisées. Mes 3 cellules sont ainsi:

  • Cell1: doit avoir une image et une étiquette.
  • Cell2: devrait avoir deux étiquettes.
  • Cell3: devrait avoir un dayPicker.

Je ne veux pas coder une balise pour les cellules. Comment puis-je gérer cela dans Swift. Dois-je coder ma propre classe pour chaque cellule? Puis-je utiliser un tableviewController? Comment puis-je remplir des données dans différentes cellules?

Je souhaite générer une tableView, comme une application de contact d'un appareil iOS.

Easyglider
la source

Réponses:

270

Permettez-moi de commencer par répondre à vos questions.

Dois-je coder une propre classe pour chaque cellule? => Oui, je le crois. Au moins, je ferais de cette façon.

Puis-je utiliser un tableviewController? => Oui, vous pouvez. Cependant, vous pouvez également avoir une vue de table dans votre contrôleur de vue.

Comment puis-je remplir des données dans différentes cellules? => Selon les conditions, vous pouvez renseigner les données dans différentes cellules. Par exemple, supposons que vous souhaitiez que vos deux premières lignes ressemblent au premier type de cellules. Donc, vous créez / réutilisez simplement le premier type de cellules et définissez ses données. Ce sera plus clair, quand je vous montrerai les captures d'écran, je suppose.

Permettez-moi de vous donner un exemple avec un TableView à l'intérieur d'un ViewController. Une fois que vous avez compris le concept principal, vous pouvez essayer de modifier comme vous le souhaitez.

Étape 1: Créez 3 TableViewCells personnalisées. Je l'ai nommé, FirstCustomTableViewCell, SecondCustomTableViewCell, ThirdCustomTableViewCell. Vous devriez utiliser des noms plus significatifs.

entrez la description de l'image ici

Étape 2: Allez dans Main.storyboard et faites glisser et déposez un TableView dans votre View Controller. Maintenant, sélectionnez la vue de table et accédez à l'inspecteur d'identité. Définissez "Prototype Cells" sur 3. Ici, vous venez de dire à votre TableView que vous pouvez avoir 3 types de cellules différents.

entrez la description de l'image ici

Étape 3: Maintenant, sélectionnez la 1ère cellule dans votre TableView et dans l'inspecteur d'identité, mettez «FirstCustomTableViewCell» dans le champ Classe personnalisée, puis définissez l'identificateur comme «firstCustomCell» dans l'inspecteur d'attributs.

entrez la description de l'image ici

entrez la description de l'image ici

Faites de même pour tous les autres: définissez leurs classes personnalisées sur respectivement "SecondCustomTableViewCell" et "ThirdCustomTableViewCell". Définissez également les identificateurs comme secondCustomCell et thirdCustomCell consécutivement.

Étape 4: Modifiez les classes de cellules personnalisées et ajoutez des prises en fonction de vos besoins. Je l'ai édité en fonction de votre question.

PS: Vous devez mettre les points de vente sous la définition de classe.

Ainsi, dans le FirstCustomTableViewCell.swift, sous le

class FirstCustomTableViewCell: UITableViewCell {

vous mettriez votre étiquette et vos prises de vue d'image.

 @IBOutlet weak var myImageView: UIImageView!
 @IBOutlet weak var myLabel: UILabel!

et dans SecondCustomTableViewCell.swift, ajoutez les deux étiquettes comme-

import UIKit

class SecondCustomTableViewCell: UITableViewCell {

    @IBOutlet weak var myLabel_1: UILabel!
    @IBOutlet weak var myLabel_2: UILabel!

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

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

et le ThirdCustomTableViewCell.swift devrait ressembler à -

import UIKit

class ThirdCustomTableViewCell: UITableViewCell {

    @IBOutlet weak var dayPicker: UIDatePicker!

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

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

Étape 5: Dans votre ViewController, créez une prise pour votre TableView et définissez la connexion à partir du storyboard. En outre, vous devez ajouter UITableViewDelegate et UITableViewDataSource dans la définition de classe en tant que liste de protocoles. Donc, votre définition de classe devrait ressembler à -

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

Ensuite, attachez les UITableViewDelegate et UITableViewDatasource de votre vue de table à votre contrôleur. À ce stade, votre viewController.swift devrait ressembler à-

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

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

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

PS: Si vous aviez utilisé un TableViewController plutôt qu'un TableView dans un ViewController, vous auriez pu ignorer cette étape.

Étape 6: Faites glisser et déposez les vues d'image et les étiquettes dans votre cellule en fonction de la classe Cell. puis fournissez une connexion à leurs points de vente à partir du storyboard.

Étape 7: Maintenant, écrivez les méthodes requises de UITableViewDatasource dans le contrôleur de vue.

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

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

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "firstCustomCell")
            //set the data here
            return cell
        }
        else if indexPath.row == 1 {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "secondCustomCell")
            //set the data here
            return cell
        }
        else {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "thirdCustomCell")
            //set the data here
            return cell
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
Natasha
la source
1
Je reçois le message: "Impossible de convertir la valeur de type 'UITableViewCell' (0x1dfbfdc) en 'Projekt.TitelTableViewCell' (0x89568)" dans le func cellForRowAtIndexPath. J'utilise un UITableViewController et j'ai une classe "TitelTableViewCell" pour ma cellule personnalisée "TitelZelle", que j'ai définie dans l'inspecteur d'identité de la cellule "TitelZelle". Que dois-je faire?
Easyglider
J'ai jeté ma cellule comme! TitelTableViewCell pour remplir mes éléments d'interface utilisateur personnalisés dans cette cellule.
Easyglider
7
essayez ceci => laissez cell = tableView.dequeueReusableCellWithIdentifier ("TitelZelle", forIndexPath: indexPath) comme TitelTableViewCell
Natasha
2
@PradipKumar, quel est le problème? Quelle est votre erreur? Btw, vous devriez poser une question si vous avez des questions. Le commentaire censé aider à comprendre ou à clarifier cela concernant le problème particulier, l'auteur a posté. Si vous avez un problème, vous devriez aller poser une question et commencer votre propre message.
Natasha
1
numberOfRowsInSection aide la tableview à déterminer le nombre de lignes souhaitées. Donc, vous ne devez fournir qu'une clause qui aidera la méthode à déterminer le nombre de lignes. indexpath.row == 0 signifiant que vous avez déjà une ligne mais à ce moment-là, votre table ne sait pas si elle a une ligne ou non. Alors, tu devrais faire comme ça.
Natasha
32

Mise à jour Swift 3.0 + avec code minimum

Concept de base: créer une vue de tableau avec des prototypes de cellules dynamiques. Attribuez un identificateur et créez une classe de cellule de vue tableau personnalisée pour chaque prototype de cellule. Lancez et affichez des cellules personnalisées dans la méthode déléguée de la vue tableau.

1. Créez des cellules sur le storyboard

Faites glisser une tableView vers votre contrôleur de vue, ajoutez-y des cellules prototypes, puis déposez l'élément d'interface utilisateur dans vos cellules de vue de table, ajoutez correctement la contrainte si nécessaire.

entrez la description de l'image ici

2. Créez des UITableViewCellclasses personnalisées

Ajoutez le code suivant à votre projet. Je le mets juste au-dessus de la classe de contrôleur de vue.

class FirstTableCell: UITableViewCell {
}

class SecondTableCell: UITableViewCell {
}

class ThirdTableCell: UITableViewCell {   
}

3. Attribuer une classe et un identificateur personnalisés aux prototypes de cellule

Pour chacun des prototypes de cellule du storyboard, attribuez la classe personnalisée créée à partir de l'étape 2, puis entrez un identifiant unique.

entrez la description de l'image ici

4. Connectez les éléments de l'interface utilisateur au code Swift

Contrôle faites glisser la vue de table et connectez-vous à la classe de contrôleur de vue. Contrôle faites glisser les éléments d'interface utilisateur ajoutés aux prototypes de cellule à l'étape 1 et connectez-vous à la classe de cellule de vue tableau correspondante.

entrez la description de l'image ici

5. Ajoutez du code pour afficher le contrôleur et contrôler la vue de la table

Rendre votre contrôleur de vue conforme au délégué de vue de table

class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

Dans viewDidLoad, configurez le délégué et la source de données de la vue tableau.

override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.dataSource = self
    self.tableView.delegate = self

}

Enfin, ajoutez deux méthodes de délégué pour contrôler votre vue de table, selon l'exigence minimale.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "firstTableCell") as! FirstTableCell
        // Set up cell.label
        return cell
    } else if indexPath.row == 1 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "secondTableCell") as! SecondTableCell
        // Set up cell.button
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "thirdTableCell") as! ThirdTableCell
        // Set up cell.textField
        return cell
    }
}

6. Essayez-le :)

entrez la description de l'image ici

Fangming
la source
Fantastique! J'adore vos animations.
iphaaw
Pouvez-vous me dire s'il est possible de mettre un en-tête pour chaque cellule? si c'est le cas, comment?
Pruthvi Hariharan
@PruthviHariharan si vous voulez avoir un «en-tête» pour toutes ou la plupart de vos cellules, ce n'est pas une bonne idée d'implémenter une cellule d'en-tête ou des en-têtes de section, qui nécessitent plus de code à gérer et affecteront les performances. Ma suggestion est de mettre une vue au-dessus de votre cellule prototype et de la faire ressembler à un "en-tête"
Fangming
@FangmingNing Pourriez-vous s'il vous plaît expliquer avec un petit exemple. Merci
Pruthvi Hariharan
Vous n'avez pas besoin de l'étape 5 si vous utilisez UITableViewController au lieu d'un UIViewController.
Deepak Thakur
0

Les réponses ci-dessus sont les meilleures réponses, mais il y a des tonnes de raisons pour obtenir ce problème. Voici une autre solution potentielle pour toute personne ayant ce problème:

Mon problème était que je passais à la classe ViewController et non à la vue du storyboard. Ma référence à la cellule du storyboard n'avait donc aucun sens, puisque le storyboard n'était pas utilisé.

Je faisais ceci:

let viewControllerB = SubViewController()
viewControllerB.passedData = diseases[indexPath.row].name
navigationController?.pushViewController(viewControllerB, animated: true)

Et j'avais besoin de faire quelque chose comme ça:

let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "SubViewStoryboardController") as! SubViewController
nextViewController.passedData = diseases[indexPath.row].name
self.present(nextViewController, animated:true, completion:nil)

J'espère que cela aide quelqu'un.

Coltuxumab
la source
-22

UITableViewControllerhérite UIViewControllerqui a déjà UITableviewDataSource&UITableviewDelegate cartographiés sur lui - même.

Vous pouvez sous-classer UITableViewControllerou utiliser un à l' TableViewintérieur de votre ViewController. Après cela, vous devez implémenter les méthodes requises ( cellForRowAtIndexPath and numberOfRowsInSection) qui sont déclarées dans leUITableviewDataSource .

Toujours dans le storyboard, vous devez créer des prototypes de cellules avec un identifiant unique.

Il existe des types de cellules de base, avec (titre, sous-titre par exemple) - vous pouvez également les utiliser si vous n'avez pas besoin de configuration spéciale.

Donc, pour le sélecteur, oui, vous devez créer votre propre cellule personnalisée. Créez le UITableViewCellsélecteur de date de conservation de classe personnalisé nécessaire et assurez-vous d'utiliser un délégué pour renvoyer le résultat souhaité à votre ViewController.

siarheibrazil
la source