UITableview z więcej niż jedną komórką niestandardową w Swift

111

Chcę używać widoku UITableview z różnymi niestandardowymi tableViewCells. Moje 3 komórki to:

  • Cell1: powinien mieć obraz i etykietę.
  • Cell2: powinien mieć dwie etykiety.
  • Cell3: powinien mieć dayPicker.

Nie chcę kodować tagu dla komórek. Jak mogę sobie z tym poradzić w Swift. Czy muszę kodować własną klasę dla każdej komórki? Czy mogę używać jednego tableviewController? Jak mogę wypełnić dane w różnych komórkach?

Chciałbym wygenerować tableView, jak aplikację kontaktową na urządzeniu z systemem iOS.

Easyglider
źródło

Odpowiedzi:

270

Zacznę najpierw od odpowiedzi na twoje pytania.

Czy muszę kodować własną klasę dla każdej komórki? => Tak, uważam, że tak. Przynajmniej zrobiłbym to w ten sposób.

Czy mogę użyć jednego tableviewController? => Tak, możesz. Możesz jednak mieć również widok tabeli w kontrolerze widoku.

Jak mogę wypełnić dane w różnych komórkach? => W zależności od warunków możesz wypełnić dane w różnych komórkach. Na przykład załóżmy, że chcesz, aby pierwsze dwa wiersze przypominały komórki pierwszego typu. Po prostu tworzysz / ponownie używasz pierwszego typu komórek i ustawiasz jego dane. Myślę, że będzie wyraźniej, gdy pokażę ci zrzuty ekranu.

Podam przykład z TableView wewnątrz ViewController. Gdy zrozumiesz główną koncepcję, możesz spróbować zmodyfikować ją tak, jak chcesz.

Krok 1: Utwórz 3 niestandardowe TableViewCells. Nazwałem to, FirstCustomTableViewCell, SecondCustomTableViewCell, ThirdCustomTableViewCell. Powinieneś używać bardziej znaczących nazw.

wprowadź opis obrazu tutaj

Krok 2: Przejdź do Main.storyboard i przeciągnij i upuść TableView do kontrolera widoku. Teraz wybierz widok tabeli i przejdź do inspektora tożsamości. Ustaw "Prototype Cells" na 3. Tutaj właśnie powiedziałeś swojemu TableView, że możesz mieć 3 różne rodzaje komórek.

wprowadź opis obrazu tutaj

Krok 3: Teraz wybierz pierwszą komórkę w swoim TableView i inspektorze tożsamości, umieść „FirstCustomTableViewCell” w polu Klasa niestandardowa, a następnie ustaw identyfikator jako „firstCustomCell” w inspektorze atrybutów.

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj

Zrób to samo dla wszystkich innych - ustaw ich klasy niestandardowe odpowiednio jako „SecondCustomTableViewCell” i „ThirdCustomTableViewCell”. Ustaw również identyfikatory kolejno jako secondCustomCell i thirdCustomCell.

Krok 4: Edytuj niestandardowe klasy komórek i dodaj gniazda zgodnie z potrzebami. Zredagowałem go na podstawie twojego pytania.

PS: Musisz umieścić wyloty w definicji klasy.

Tak więc w pliku FirstCustomTableViewCell.swift pod

class FirstCustomTableViewCell: UITableViewCell {

umieściłbyś swoją etykietę i punkty wyświetlania obrazu.

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

aw SecondCustomTableViewCell.swift dodaj dwie etykiety, takie jak-

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

a ThirdCustomTableViewCell.swift powinien wyglądać następująco:

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

Krok 5: W swoim ViewController utwórz Outlet dla swojego TableView i ustaw połączenie z storyboardu. Ponadto należy dodać UITableViewDelegate i UITableViewDataSource w definicji klasy jako listę protokołów. Twoja definicja klasy powinna wyglądać następująco:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

Następnie dołącz UITableViewDelegate i UITableViewDatasource widoku tabeli do kontrolera. W tym momencie twój viewController.swift powinien wyglądać następująco:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

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

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

PS: Jeśli chcesz użyć TableViewController zamiast TableView wewnątrz ViewController, możesz pominąć ten krok.

Krok 6: Przeciągnij i upuść widoki obrazów i etykiety w komórce zgodnie z klasą Cell. a następnie zapewnić połączenie z ich gniazdami ze scenorysu.

Krok 7: Teraz zapisz wymagane metody UITableViewDatasource w kontrolerze widoku.

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()
    }
}
Natasza
źródło
1
Otrzymuję komunikat: „Nie można rzutować wartości typu„ UITableViewCell ”(0x1dfbfdc) na„ Projekt.TitelTableViewCell ”(0x89568)” w func cellForRowAtIndexPath. Używam UITableViewController i mam klasę „TitelTableViewCell” dla mojej niestandardowej komórki „TitelZelle”, którą ustawiłem w inspektorze tożsamości komórki „TitelZelle”. Co mam do zrobienia?
Easyglider
Odrzuciłem swoją komórkę jako! TitelTableViewCell, aby wypełnić moje niestandardowe elementy interfejsu użytkownika w tej komórce.
Easyglider
7
spróbuj this => let cell = tableView.dequeueReusableCellWithIdentifier ("TitelZelle", forIndexPath: indexPath) jako TitelTableViewCell
Natasha
2
@PradipKumar, w czym problem? Jaki jest twój błąd? Przy okazji, jeśli masz jakieś pytania, zadaj pytanie. Komentarz, który ma pomóc w zrozumieniu lub wyjaśnieniu tego w odniesieniu do konkretnego problemu, zamieścił autor. Jeśli masz problem, powinieneś przejść do zadania pytania i rozpocząć własny post.
Natasha
1
numberOfRowsInSection pomaga widokowi tabeli określić, ile chcemy wierszy. Dlatego należy podać tylko klauzulę, która pomoże metodzie określić liczbę wierszy. indexpath.row == 0 oznacza, że ​​masz już wiersz, ale w tym czasie Twoja tabela nie wie, czy ma wiersz, czy nie. Więc powinieneś to zrobić.
Natasha
32

Aktualizacja Swift 3.0 + z minimalnym kodem

Podstawowa koncepcja: Utwórz widok tabeli z dynamicznymi prototypami komórek. Przypisz identyfikator i utwórz niestandardową klasę komórek widoku tabeli dla każdego prototypu komórki. Zainicjuj i pokaż komórki niestandardowe w metodzie delegata widoku tabeli.

1. Utwórz komórki w serii ujęć

Przeciągnij tableView do kontrolera widoku, dodaj do niego komórki prototypu, a następnie upuść element interfejsu użytkownika do komórek widoku tabeli, w razie potrzeby dodaj ograniczenie poprawnie.

wprowadź opis obrazu tutaj

2. Utwórz własne UITableViewCellklasy

Dodaj następujący kod do projektu. Umieszczam to tuż nad klasą kontrolera widoku.

class FirstTableCell: UITableViewCell {
}

class SecondTableCell: UITableViewCell {
}

class ThirdTableCell: UITableViewCell {   
}

3. Przypisz niestandardową klasę i identyfikator do prototypów komórek

Do każdego z prototypów komórek w scenorysie przypisz niestandardową klasę utworzoną w kroku 2, a następnie wprowadź unikalny identyfikator.

wprowadź opis obrazu tutaj

4. Połącz elementy UI w szybki kod

Kontroluj przeciągnij widok tabeli i połącz się z klasą kontrolera widoku. Sterowanie przeciągnij elementy interfejsu użytkownika, które zostaną dodane do prototypów komórek w kroku 1, i połącz się z odpowiednią klasą komórek widoku tabeli.

wprowadź opis obrazu tutaj

5. Dodaj kod, aby wyświetlić kontroler i sterować widokiem tabeli

Spraw, aby kontroler widoku był zgodny z delegatem widoku tabeli

class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

W programie viewDidLoadskonfiguruj delegata widoku tabeli i źródło danych.

override func viewDidLoad() {
    super.viewDidLoad()

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

}

Na koniec dodaj dwie metody delegatów, aby kontrolować widok tabeli, zgodnie z minimalnymi wymaganiami.

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. Spróbuj :)

wprowadź opis obrazu tutaj

Fangming
źródło
Fantastyczny! Uwielbiam Twoje animacje.
iphaaw
Czy możesz mi powiedzieć, czy można umieścić nagłówek dla każdej komórki? Jeśli tak to jak?
Pruthvi Hariharan
@PruthviHariharan jeśli chcesz mieć „nagłówek” dla każdej lub większości komórek, nie jest dobrym pomysłem zaimplementowanie komórki nagłówka lub nagłówków sekcji, które wymagają więcej kodu do zarządzania i wpłyną na wydajność.
Proponuję
@FangmingNing Czy mógłbyś wyjaśnić na małym przykładzie. Dziękuję
Pruthvi Hariharan
Nie potrzebujesz kroku 5, jeśli używasz UITableViewController zamiast UIViewController.
Deepak Thakur
0

Powyższe odpowiedzi są najlepszymi odpowiedziami, ale istnieje mnóstwo powodów, aby uzyskać ten problem. Oto kolejne potencjalne rozwiązanie dla każdego, kto ma ten problem:

Mój problem polegał na tym, że przechodziłem do klasy ViewController, a nie do widoku scenorysu. Więc moje odniesienie do komórki storyboardowej było bez znaczenia, ponieważ storyboard nie był używany.

Robiłem to:

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

Musiałem zrobić coś takiego:

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)

Mam nadzieję, że to komuś pomoże.

Coltuxumab
źródło
-22

UITableViewControllerdziedziczy UIViewControllerto, co już zostało UITableviewDataSource& UITableviewDelegatezmapowane na sobie.

Możesz podklasować UITableViewControllerlub użyć TableViewwewnątrz swojej ViewController. Następnie należy zaimplementować wymagane metody ( cellForRowAtIndexPath and numberOfRowsInSection), które są zadeklarowane w pliku UITableviewDataSource.

Również w scenorysie musisz stworzyć prototypy komórek z unikalnym identyfikatorem.

Istnieją podstawowe typy komórek, z (na przykład tytuł, podtytuł) - możesz ich również użyć, jeśli nie potrzebujesz specjalnej konfiguracji.

Tak więc w przypadku selektora tak, musisz utworzyć własną niestandardową komórkę. Utwórz niezbędny UITableViewCellselektor dat przechowywania klas niestandardowych i upewnij się, że używasz delegata, aby odesłać żądany wynik z powrotem do swojego ViewController.

siarheibrazil
źródło