UITableview mit mehr als einer benutzerdefinierten Zelle mit Swift

111

Ich möchte eine UITableview mit verschiedenen benutzerdefinierten tableViewCells verwenden. Meine 3 Zellen sind als solche:

  • Zelle1: sollte ein Bild und eine Beschriftung haben.
  • Zelle2: sollte zwei Beschriftungen haben.
  • Cell3: sollte einen dayPicker haben.

Ich möchte kein Tag für die Zellen codieren. Wie kann ich das in Swift schaffen? Muss ich für jede Zelle meine eigene Klasse codieren? Kann ich einen tableviewController verwenden? Wie kann ich Daten in verschiedenen Zellen füllen?

Ich möchte eine Tabellenansicht generieren, wie eine Kontakt-App eines iOS-Geräts.

Easyglider
quelle

Antworten:

269

Lassen Sie mich zunächst Ihre Fragen beantworten.

Muss ich für jede Zelle eine eigene Klasse codieren? => Ja, ich glaube schon. Zumindest würde ich das so machen.

Kann ich einen tableviewController verwenden? => Ja, das können Sie. Sie können jedoch auch eine Tabellenansicht in Ihrem View Controller haben.

Wie kann ich Daten in verschiedenen Zellen füllen? => Abhängig von den Bedingungen können Sie Daten in verschiedenen Zellen auffüllen. Angenommen, Sie möchten, dass Ihre ersten beiden Zeilen dem ersten Zelltyp entsprechen. Sie erstellen / verwenden also einfach den ersten Zelltyp und legen dessen Daten fest. Es wird klarer, wenn ich Ihnen die Screenshots zeige, denke ich.

Lassen Sie mich Ihnen ein Beispiel mit einer TableView in einem ViewController geben. Sobald Sie das Hauptkonzept verstanden haben, können Sie versuchen, es nach Belieben zu ändern.

Schritt 1: Erstellen Sie 3 benutzerdefinierte TableViewCells. Ich habe es FirstCustomTableViewCell, SecondCustomTableViewCell, ThirdCustomTableViewCell genannt. Sie sollten aussagekräftigere Namen verwenden.

Geben Sie hier die Bildbeschreibung ein

Schritt 2: Gehen Sie zum Main.storyboard und ziehen Sie eine TableView per Drag & Drop in Ihren View Controller. Wählen Sie nun die Tabellenansicht aus und rufen Sie den Identitätsinspektor auf. Setzen Sie den "Prototyp Cells" auf 3. Hier haben Sie Ihrem TableView gerade mitgeteilt, dass Sie möglicherweise 3 verschiedene Arten von Zellen haben.

Geben Sie hier die Bildbeschreibung ein

Schritt 3: Wählen Sie nun die erste Zelle in Ihrer TableView und im Identitätsinspektor aus, geben Sie "FirstCustomTableViewCell" in das Feld "Benutzerdefinierte Klasse" ein und legen Sie den Bezeichner im Attributinspektor als "firstCustomCell" fest.

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Machen Sie dasselbe für alle anderen - Legen Sie ihre benutzerdefinierten Klassen als "SecondCustomTableViewCell" bzw. "ThirdCustomTableViewCell" fest. Legen Sie außerdem die Bezeichner nacheinander als secondCustomCell und ThirdCustomCell fest.

Schritt 4: Bearbeiten Sie die benutzerdefinierten Zellenklassen und fügen Sie nach Bedarf Steckdosen hinzu. Ich habe es basierend auf Ihrer Frage bearbeitet.

PS: Sie müssen die Steckdosen unter die Klassendefinition stellen.

Also, in der FirstCustomTableViewCell.swift, unter dem

class FirstCustomTableViewCell: UITableViewCell {

Sie würden Ihre Etiketten- und Bildansicht-Steckdosen platzieren.

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

Fügen Sie in SecondCustomTableViewCell.swift die beiden Beschriftungen wie folgt hinzu:

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)
    }
}

und die ThirdCustomTableViewCell.swift sollte wie folgt aussehen:

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)
    }
}

Schritt 5: Erstellen Sie in Ihrem ViewController ein Outlet für Ihre TableView und stellen Sie die Verbindung über das Storyboard her. Außerdem müssen Sie UITableViewDelegate und UITableViewDataSource in der Klassendefinition als Protokollliste hinzufügen. Ihre Klassendefinition sollte also so aussehen:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

Hängen Sie anschließend die UITableViewDelegate und UITableViewDatasource Ihrer Tabellenansicht an Ihren Controller an. Zu diesem Zeitpunkt sollte Ihr viewController.swift wie folgt aussehen:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

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

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

PS: Wenn Sie einen TableViewController anstelle eines TableView in einem ViewController verwenden würden, hätten Sie diesen Schritt überspringen können.

Schritt 6: Ziehen Sie die Bildansichten und Beschriftungen entsprechend der Cell-Klasse in Ihre Zelle und legen Sie sie dort ab. und stellen Sie dann über das Storyboard eine Verbindung zu ihren Steckdosen her.

Schritt 7: Schreiben Sie nun die erforderlichen Methoden der UITableViewDatasource in den View Controller.

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()
    }
}
Natascha
quelle
1
Ich erhalte die Meldung: "Wert vom Typ 'UITableViewCell' (0x1dfbfdc) konnte nicht in 'Projekt.TitelTableViewCell' (0x89568) umgewandelt werden" in der Funktion cellForRowAtIndexPath. Ich verwende einen UITableViewController und habe eine Klasse "TitelTableViewCell" für meine benutzerdefinierte Zelle "TitelZelle", die ich im Identitätsinspektor der Zelle "TitelZelle" festgelegt habe. Was muss ich tun?
Easyglider
Ich habe meine Zelle als gegossen! TitelTableViewCell, um meine benutzerdefinierten UI-Elemente in dieser Zelle zu füllen.
Easyglider
7
Versuchen Sie dies => let cell = tableView.dequeueReusableCellWithIdentifier ("TitelZelle", forIndexPath: indexPath) als TitelTableViewCell
Natasha
2
@PradipKumar, was ist das Problem? Was ist dein Fehler? Übrigens sollten Sie eine Frage stellen, wenn Sie Fragen haben. Der Kommentar, der dazu beitragen soll, dies in Bezug auf das jeweilige Problem zu verstehen oder zu klären, hat der Autor veröffentlicht. Wenn Sie ein Problem haben, sollten Sie Fragen stellen und einen eigenen Beitrag erstellen.
Natasha
1
Mit numberOfRowsInSection kann die Tabellenansicht bestimmen, wie viele Zeilen wir möchten. Sie sollten daher nur eine Klausel angeben, mit deren Hilfe die Methode die Anzahl der Zeilen bestimmen kann. indexpath.row == 0 bedeutet, dass Sie bereits eine Zeile haben, aber zu diesem Zeitpunkt weiß Ihre Tabelle nicht, ob sie eine Zeile enthält oder nicht. Also solltest du das tun.
Natasha
32

Swift 3.0 + Update mit minimalem Code

Grundkonzept: Erstellen Sie eine Tabellenansicht mit dynamischen Zellprototypen. Weisen Sie einen Bezeichner zu und erstellen Sie eine benutzerdefinierte Tabellenklasse für die Tabellenansicht für jeden Zellenprototyp. Initiieren und Anzeigen von benutzerdefinierten Zellen in der Delegatenmethode der Tabellenansicht.

1. Erstellen Sie Zellen im Storyboard

Ziehen Sie eine Tabellenansicht auf Ihren Ansichtscontroller, fügen Sie Prototypzellen hinzu, und legen Sie dann das UI-Element in Ihren Tabellenansichtszellen ab. Fügen Sie bei Bedarf Einschränkungen ordnungsgemäß hinzu.

Geben Sie hier die Bildbeschreibung ein

2. Erstellen Sie benutzerdefinierte UITableViewCellKlassen

Fügen Sie Ihrem Projekt den folgenden Code hinzu. Ich setze es direkt über die View Controller-Klasse.

class FirstTableCell: UITableViewCell {
}

class SecondTableCell: UITableViewCell {
}

class ThirdTableCell: UITableViewCell {   
}

3. Weisen Sie den Zellprototypen eine benutzerdefinierte Klasse und Kennung zu

Weisen Sie für jeden der Zellprototypen im Storyboard die aus Schritt 2 erstellte benutzerdefinierte Klasse zu und geben Sie dann eine eindeutige Kennung ein.

Geben Sie hier die Bildbeschreibung ein

4. Verbinden Sie UI-Elemente mit schnellem Code

Ziehen Sie bei gedrückter Ctrl-Taste die Tabellenansicht und stellen Sie eine Verbindung zur View-Controller-Klasse her. Ziehen Sie die UI-Elemente, die in Schritt 1 zu Zellprototypen hinzugefügt werden, und stellen Sie eine Verbindung zur entsprechenden Zellenklasse der Tabellenansicht her.

Geben Sie hier die Bildbeschreibung ein

5. Fügen Sie Code hinzu, um den Controller anzuzeigen und die Tabellenansicht zu steuern

Passen Sie Ihren View Controller an den Delegierten der Tabellenansicht an

class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

In viewDidLoad, Tabelle nach Ansicht der Delegierten und Datenquelle einrichten.

override func viewDidLoad() {
    super.viewDidLoad()

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

}

Fügen Sie abschließend zwei Delegierungsmethoden hinzu, um Ihre Tabellenansicht gemäß den Mindestanforderungen zu steuern.

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. Probieren Sie es aus :)

Geben Sie hier die Bildbeschreibung ein

Fangming
quelle
Fantastisch! Ich liebe deine Animationen.
Iphaaw
Könnten Sie mir bitte sagen, ob es möglich ist, für jede Zelle einen Header zu setzen? Wenn das so ist, wie?
Pruthvi Hariharan
@PruthviHariharan Wenn Sie für jede oder die meisten Ihrer Zellen einen „Header“ haben möchten, ist es keine gute Idee, eine Header-Zelle oder einen Abschnittsheader zu implementieren, für dessen Verwaltung mehr Code erforderlich ist und die die Leistung beeinträchtigt. Mein Vorschlag ist, eine Ansicht auf Ihre Prototypzelle zu setzen und sie wie einen „Header“ aussehen zu lassen
Fangming
@FangmingNing Könnten Sie bitte mit einem kleinen Beispiel erklären. Vielen Dank
Pruthvi Hariharan
0

Die obigen Antworten sind die besten Antworten, aber es gibt Unmengen von Gründen, um dieses Problem zu bekommen. Hier ist eine weitere mögliche Lösung für alle mit diesem Problem:

Mein Problem war, dass ich zur ViewController-Klasse und nicht zur Storyboard-Ansicht überging. Mein Verweis auf die Storyboard-Zelle war also bedeutungslos, da das Storyboard nicht verwendet wurde.

Ich habe das gemacht:

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

Und ich musste so etwas tun:

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)

Hoffe das hilft jemandem.

Coltuxumab
quelle
-22

UITableViewControllererbt UIViewController, das bereits UITableviewDataSource& UITableviewDelegateauf sich selbst abgebildet hat.

Sie können eine Unterklasse UITableViewControlleroder eine TableViewin Ihrem verwenden ViewController. Danach müssen Sie die erforderlichen Methoden ( cellForRowAtIndexPath and numberOfRowsInSection) implementieren, die in der deklariert sind UITableviewDataSource.

Auch im Storyboard müssen Sie Zellprototypen mit eindeutiger ID erstellen.

Es gibt grundlegende Zelltypen mit (z. B. Titel, Untertitel) - Sie können sie auch verwenden, wenn Sie keine spezielle Konfiguration benötigen.

Für die Auswahl müssen Sie also eine eigene benutzerdefinierte Zelle erstellen. Erstellen Sie die erforderliche benutzerdefinierte UITableViewCellAuswahl für das Halten von Klassen und stellen Sie sicher, dass Sie mit delegate das gewünschte Ergebnis an Ihre senden ViewController.

Siarheibrazil
quelle