UITableview com mais de uma célula personalizada com Swift

111

Eu quero usar um UITableview com diferentes tableViewCells personalizadas. Minhas 3 células são as seguintes:

  • Cell1: deve ter uma imagem e um rótulo.
  • Cell2: deve ter dois rótulos.
  • Cell3: deve ter um dayPicker.

Não quero codificar uma tag para as células. Como posso gerenciar isso no Swift. Tenho que codificar minha própria classe para cada célula? Posso usar um tableviewController? Como posso preencher dados em células diferentes?

Gostaria de gerar um tableView, como um aplicativo de contato de um dispositivo iOS.

Easyglider
fonte

Respostas:

270

Deixe-me começar respondendo suas perguntas primeiro.

Tenho que codificar uma classe própria para cada célula? => Sim, acredito que sim. Pelo menos, eu faria assim.

Posso usar um tableviewController? => Sim, você pode. No entanto, você também pode ter uma visão de tabela dentro de seu View Controller.

Como posso preencher dados em células diferentes? => Dependendo das condições, você pode preencher dados em células diferentes. Por exemplo, vamos supor que você deseja que suas duas primeiras linhas sejam como o primeiro tipo de células. Então, você apenas cria / reutiliza o primeiro tipo de células e define seus dados. Ficará mais claro quando eu mostrar as capturas de tela, eu acho.

Deixe-me dar um exemplo com um TableView dentro de um ViewController. Depois de entender o conceito principal, você pode tentar e modificar como quiser.

Etapa 1: Crie 3 TableViewCells personalizadas. Eu o chamei de FirstCustomTableViewCell, SecondCustomTableViewCell, ThirdCustomTableViewCell. Você deve usar nomes mais significativos.

insira a descrição da imagem aqui

Etapa 2: Vá para Main.storyboard e arraste e solte uma TableView dentro de seu View Controller. Agora, selecione a visualização da tabela e vá para o inspetor de identidade. Defina "Prototype Cells" como 3. Aqui, você acabou de dizer ao TableView que pode ter 3 tipos diferentes de células.

insira a descrição da imagem aqui

Etapa 3: Agora, selecione a 1ª célula em sua TableView e no inspetor de identidade, coloque "FirstCustomTableViewCell" no campo Classe personalizada e defina o identificador como "firstCustomCell" no inspetor de atributos.

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Faça o mesmo para todos os outros - defina suas classes personalizadas como "SecondCustomTableViewCell" e "ThirdCustomTableViewCell", respectivamente. Defina também os identificadores como secondCustomCell e thirdCustomCell consecutivamente.

Etapa 4: edite as classes de células personalizadas e adicione pontos de venda de acordo com sua necessidade. Eu editei com base na sua pergunta.

PS: Você precisa colocar as saídas sob a definição de classe.

Portanto, em FirstCustomTableViewCell.swift, sob o

class FirstCustomTableViewCell: UITableViewCell {

você colocaria seu rótulo e pontos de exibição de imagem.

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

e no SecondCustomTableViewCell.swift, adicione os dois rótulos como-

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

e o ThirdCustomTableViewCell.swift deve ser semelhante a-

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

Etapa 5: Em seu ViewController, crie um Outlet para seu TableView e defina a conexão do storyboard. Além disso, você precisa adicionar UITableViewDelegate e UITableViewDataSource na definição de classe como a lista de protocolo. Portanto, a definição de sua classe deve ser semelhante a

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

Depois disso, anexe UITableViewDelegate e UITableViewDatasource de sua visualização de tabela ao seu controlador. Neste ponto, seu viewController.swift deve ser semelhante a-

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

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

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

PS: Se você fosse usar um TableViewController em vez de um TableView dentro de um ViewController, você poderia pular esta etapa.

Etapa 6: arraste e solte as visualizações e rótulos da imagem em sua célula de acordo com a classe Cell. e, em seguida, fornecer conexão com seus pontos de venda do storyboard.

Etapa 7: Agora, escreva os métodos necessários do UITableViewDatasource no controlador de visualização.

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
fonte
1
Recebo a mensagem: "Não foi possível converter o valor do tipo 'UITableViewCell' (0x1dfbfdc) para 'Projekt.TitelTableViewCell' (0x89568)" na função cellForRowAtIndexPath. Estou usando um UITableViewController e tenho uma classe "TitelTableViewCell" para minha célula personalizada "TitelZelle", que configurei no inspetor de identidade da célula "TitelZelle". O que eu tenho que fazer?
Easyglider
Eu lancei meu celular como! TitelTableViewCell para preencher meus elementos de IU personalizados nesta célula.
Easyglider
7
tente isto => let cell = tableView.dequeueReusableCellWithIdentifier ("TitelZelle", forIndexPath: indexPath) como TitelTableViewCell
Natasha
2
@PradipKumar, qual é o problema? Qual é o seu erro? Aliás, você deve fazer uma pergunta se tiver alguma dúvida. O comentário postou o autor para ajudar a entender ou esclarecer isso em relação ao problema específico. Se você tiver um problema, deve ir fazer perguntas e começar sua própria postagem.
Natasha
1
numberOfRowsInSection ajuda a tableview a determinar quantas linhas queremos. Portanto, você só deve fornecer cláusulas que ajudem o método a determinar o número de linhas. indexpath.row == 0 significa que você já tem uma linha, mas naquele momento, sua tabela não sabe se tem uma linha ou não. Então, você deve fazer assim.
Natasha
32

Swift 3.0 + atualização com código mínimo

Conceito básico: Crie uma visualização de tabela com protótipos de células dinâmicas. Atribua um identificador e crie uma classe de célula de visualização de tabela customizada para cada protótipo de célula. Inicie e mostre células personalizadas no método de delegação da visualização de tabela.

1. Crie células no storyboard

Arraste uma tableView para seu controlador de visualização, adicione células de protótipo a ela e, em seguida, solte o elemento de interface do usuário nas células de visualização de sua tabela, adicione a restrição adequadamente, se necessário.

insira a descrição da imagem aqui

2. Crie UITableViewCellclasses personalizadas

Adicione o seguinte código ao seu projeto. Estou colocando logo acima da classe do controlador de exibição.

class FirstTableCell: UITableViewCell {
}

class SecondTableCell: UITableViewCell {
}

class ThirdTableCell: UITableViewCell {   
}

3. Atribuir classe personalizada e identificador para protótipos de células

Para cada um dos protótipos de célula no storyboard, atribua a classe personalizada criada na etapa 2 e, em seguida, insira um identificador exclusivo.

insira a descrição da imagem aqui

4. Conecte os elementos da IU ao código swift

Controle arraste a visualização da tabela e conecte-se à classe do controlador de visualização. Controle, arraste os elementos da IU que são adicionados aos protótipos de células na etapa 1 e conecte-se à classe de célula de visualização de tabela correspondente.

insira a descrição da imagem aqui

5. Adicione o código para visualizar o controlador e controlar a visualização da tabela

Faça seu controlador de visualização em conformidade com o delegado de visualização de tabela

class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

Em viewDidLoad, configure o delegado e a fonte de dados do table view.

override func viewDidLoad() {
    super.viewDidLoad()

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

}

Por fim, adicione dois métodos delegados para controlar a visualização da tabela, conforme o requisito mínimo.

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. Experimente :)

insira a descrição da imagem aqui

Fangming
fonte
Fantástico! Eu amo suas animações.
iphaaw
Você poderia me dizer, é possível colocar um cabeçalho para cada célula? se sim, como?
Pruthvi Hariharan
@PruthviHariharan se você quiser ter um “cabeçalho” para todas ou a maioria de suas células, não é uma boa ideia implementar uma célula de cabeçalho ou cabeçalhos de seção, que precisam de mais código para gerenciar e afetarão o desempenho. Minha sugestão é colocar uma visão no topo de sua célula de protótipo e fazê-la parecer um “cabeçalho”
Fangming
@FangmingNing Você poderia explicar com um pequeno exemplo. Obrigado
Pruthvi Hariharan
Você não precisa da etapa 5 se estiver usando UITableViewController em vez de UIViewController.
Deepak Thakur
0

As respostas acima são as melhores respostas, mas existem TONELADAS de razões para obter este problema. Aqui está outra solução potencial para qualquer pessoa com este problema:

Meu problema era que eu estava seguindo para a classe ViewController e não para a visualização do storyboard. Portanto, minha referência à célula do storyboard não fazia sentido, já que o storyboard não estava sendo usado.

Eu estava fazendo isso:

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

E eu precisava fazer algo assim:

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)

Espero que isso ajude alguém.

Coltuxumab
fonte
-22

UITableViewControllerestá herdando UIViewControlleraquilo que já foi UITableviewDataSource& UITableviewDelegatemapeado em si mesmo.

Você pode criar UITableViewControlleruma subclasse ou usar um TableViewdentro de seu ViewController. Depois disso, você deve implementar os métodos requeridos ( cellForRowAtIndexPath and numberOfRowsInSection) que são declarados no UITableviewDataSource.

Também no storyboard, você precisa criar protótipos de células com ID exclusivo.

Existem tipos básicos de células, com (título, subtítulo, por exemplo) - você também pode usá-los se não precisar de configuração especial.

Portanto, para o selecionador, sim, você precisa criar sua própria célula personalizada. Crie a UITableViewCellclasse personalizada necessária segurando o selecionador de data e certifique-se de usar delegado para enviar de volta o resultado desejado para o seu ViewController.

Siarheibrazil
fonte