UITableview con más de una celda personalizada con Swift

111

Quiero usar un UITableview con diferentes tableViewCells personalizados. Mis 3 celdas son como tales:

  • Cell1: debe tener una imagen y una etiqueta.
  • Cell2: debe tener dos etiquetas.
  • Cell3: debería tener un dayPicker.

No quiero codificar una etiqueta para las celdas. ¿Cómo puedo gestionar esto en Swift? ¿Tengo que codificar mi propia clase para cada celda? ¿Puedo usar un controlador de vista de tabla? ¿Cómo puedo completar datos en diferentes celdas?

Me gustaría generar un tableView, como una aplicación de contacto de un dispositivo iOS.

Easyglider
fuente

Respuestas:

270

Permítanme comenzar respondiendo sus preguntas primero.

¿Tengo que codificar una clase propia para cada celda? => Sí, eso creo. Al menos, lo haría de esa manera.

¿Puedo usar un tableviewController? => Sí, puedes. Sin embargo, también puede tener una vista de tabla dentro de su controlador de vista.

¿Cómo puedo completar datos en diferentes celdas? => Dependiendo de las condiciones, puede completar datos en diferentes celdas. Por ejemplo, supongamos que desea que sus dos primeras filas sean como el primer tipo de celdas. Por lo tanto, solo crea / reutiliza el primer tipo de celdas y establece sus datos. Será más claro, cuando les muestre las capturas de pantalla, supongo.

Permítame darle un ejemplo con un TableView dentro de un ViewController. Una vez que comprenda el concepto principal, puede intentar modificarlo de la forma que desee.

Paso 1: Cree 3 TableViewCells personalizadas. Lo nombré FirstCustomTableViewCell, SecondCustomTableViewCell, ThirdCustomTableViewCell. Debería utilizar nombres más significativos.

ingrese la descripción de la imagen aquí

Paso 2: Vaya al Main.storyboard y arrastre y suelte un TableView dentro de su View Controller. Ahora, seleccione la vista de tabla y vaya al inspector de identidad. Establezca las "Celdas prototipo" en 3. Aquí, acaba de decirle a TableView que puede tener 3 tipos diferentes de celdas.

ingrese la descripción de la imagen aquí

Paso 3: Ahora, seleccione la primera celda en su TableView y en el inspector de identidad, coloque "FirstCustomTableViewCell" en el campo Clase personalizada y luego establezca el identificador como "firstCustomCell" en el inspector de atributos.

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Haga lo mismo para todos los demás: establezca sus clases personalizadas como "SecondCustomTableViewCell" y "ThirdCustomTableViewCell" respectivamente. También configure los identificadores como secondCustomCell y thirdCustomCell consecutivamente.

Paso 4: Edite las clases de celdas personalizadas y agregue salidas de acuerdo con sus necesidades. Lo edité según tu pregunta.

PD: Necesitas poner los puntos de venta bajo la definición de clase.

Entonces, en FirstCustomTableViewCell.swift, bajo el

class FirstCustomTableViewCell: UITableViewCell {

pondría su etiqueta e imagen en los puntos de venta.

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

y en SecondCustomTableViewCell.swift, agregue las dos etiquetas 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)
    }
}

y ThirdCustomTableViewCell.swift debería verse como-

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

Paso 5: En su ViewController, cree un Outlet para su TableView y configure la conexión desde el guión gráfico. Además, debe agregar UITableViewDelegate y UITableViewDataSource en la definición de clase como lista de protocolos. Entonces, la definición de su clase debería verse así:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

Después de eso, adjunte UITableViewDelegate y UITableViewDatasource de su vista de tabla a su controlador. En este punto, su viewController.swift debería verse como-

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

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

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

PD: Si tuviera que usar un TableViewController en lugar de un TableView dentro de un ViewController, podría haber omitido este paso.

Paso 6: Arrastre y suelte las vistas de imagen y las etiquetas en su celda de acuerdo con la clase Cell. y luego proporcionar conexión a sus puntos de venta desde el guión gráfico.

Paso 7: Ahora, escriba los métodos requeridos de UITableViewDatasource en el controlador de vista.

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
fuente
1
Recibo el mensaje: "No se pudo convertir el valor del tipo 'UITableViewCell' (0x1dfbfdc) a 'Projekt.TitelTableViewCell' (0x89568)" en la función cellForRowAtIndexPath. Estoy usando un UITableViewController y tengo una clase "TitelTableViewCell" para mi celda personalizada "TitelZelle", que he configurado en el inspector de identidad de la celda "TitelZelle". ¿Que tengo que hacer?
Easyglider
¡He marcado mi celda como! TitelTableViewCell para completar mis elementos de IU personalizados en esta celda.
Easyglider
7
intente esto => let cell = tableView.dequeueReusableCellWithIdentifier ("TitelZelle", forIndexPath: indexPath) como TitelTableViewCell
Natasha
2
@PradipKumar, ¿cuál es el problema? Cual es tu error? Por cierto, debe hacer una pregunta si tiene alguna consulta. El comentario que se supone que ayuda a comprender o aclarar esto con respecto al problema en particular, ha publicado el autor. Si tiene un problema, debe ir a hacer una pregunta y comenzar su propia publicación.
Natasha
1
numberOfRowsInSection ayuda a la vista de tabla a determinar cuántas filas queremos. Por lo tanto, solo debe proporcionar una cláusula que ayude al método a determinar el número de filas. indexpath.row == 0 significa que ya tiene una fila, pero en ese momento, su tabla no sabe si tiene una fila o no. Entonces, deberías hacer eso.
Natasha
32

Swift 3.0 + actualización con código mínimo

Concepto básico: crear una vista de tabla con prototipos de celdas dinámicas. Asigne un identificador y cree una clase de celda de vista de tabla personalizada para cada prototipo de celda. Inicie y muestre celdas personalizadas en el método de delegado de la vista de tabla.

1. Crea celdas en el guión gráfico

Arrastre una vista de tabla a su controlador de vista, agregue celdas prototipo y luego suelte el elemento de la interfaz de usuario en las celdas de la vista de tabla, agregue la restricción correctamente si es necesario.

ingrese la descripción de la imagen aquí

2. Crea UITableViewCellclases personalizadas

Agregue el siguiente código a su proyecto. Lo estoy poniendo justo encima de la clase de controlador de vista.

class FirstTableCell: UITableViewCell {
}

class SecondTableCell: UITableViewCell {
}

class ThirdTableCell: UITableViewCell {   
}

3. Asignar un identificador y una clase personalizados a los prototipos de células

Para cada uno de los prototipos de celda en el guión gráfico, asigne la clase personalizada creada en el paso 2 y luego ingrese un identificador único.

ingrese la descripción de la imagen aquí

4. Conecte los elementos de la interfaz de usuario al código rápido

Control, arrastre la vista de tabla y conéctese a la clase de controlador de vista. Control, arrastre los elementos de la interfaz de usuario que se agregan a los prototipos de celda en el paso 1 y conéctese a la clase de celda de vista de tabla correspondiente.

ingrese la descripción de la imagen aquí

5. Agregue código para ver el controlador y controlar la vista de la tabla

Haga que su controlador de vista se ajuste al delegado de vista de tabla

class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

En viewDidLoad, configure el delegado y la fuente de datos de la vista de tabla.

override func viewDidLoad() {
    super.viewDidLoad()

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

}

Finalmente, agregue dos métodos delegados para controlar su vista de tabla, según el 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. Pruébalo :)

ingrese la descripción de la imagen aquí

Colmillos
fuente
¡Fantástico! Amo tus animaciones.
iphaaw
¿Podría decirme, por favor, es posible poner un encabezado para cada celda? ¿si es así, cómo?
Pruthvi Hariharan
@PruthviHariharan si desea tener un "encabezado" para todas o la mayoría de sus celdas, no es una buena idea implementar una celda de encabezado o encabezados de sección, que necesitan más código para administrar y afectarán el rendimiento. Mi sugerencia es poner una vista en la parte superior de su celda prototipo y hacer que parezca un "encabezado"
Fangming
@FangmingNing ¿Podría explicarnos con un pequeño ejemplo? Gracias
Pruthvi Hariharan
No necesita el paso 5 si está utilizando UITableViewController en lugar de UIViewController.
Deepak Thakur
0

Las respuestas anteriores son las mejores, pero hay TONELADAS de razones para tener este problema. Aquí hay otra posible solución para cualquier persona con este problema:

Mi problema fue que estaba pasando a la clase ViewController y no a la vista del guión gráfico. Así que mi referencia a la celda del guión gráfico no tenía sentido, ya que el guión gráfico no se estaba utilizando.

Estaba haciendo esto:

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

Y necesitaba hacer algo como esto:

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 esto ayude a alguien.

Coltuxumab
fuente
-22

UITableViewControllerestá heredando UIViewControllerque ya ha UITableviewDataSourcey UITableviewDelegateasignada en sí mismo.

Puede crear una subclase UITableViewControllero usar un TableViewdentro de su ViewController. Después de eso, debe implementar los métodos requeridos ( cellForRowAtIndexPath and numberOfRowsInSection) que se declaran en el UITableviewDataSource.

También en el guión gráfico, debe crear prototipos de células con una identificación única.

Hay tipos básicos de celda, con (título, subtítulo, por ejemplo); también puede usarlos si no necesita una configuración especial.

Entonces, para el selector, sí, debe crear su propia celda personalizada. Cree el UITableViewCellselector de fecha de celebración de clases personalizado necesario y asegúrese de usar delegado para devolver el resultado deseado a su ViewController.

siarheibrazil
fuente