¿Cómo se cargan las UITableViewCells personalizadas desde los archivos Xib?

votos
278

La pregunta es simple: ¿cómo se cargan los UITableViewCellarchivos Xib personalizados ? Hacerlo le permite usar Interface Builder para diseñar sus celdas. La respuesta aparentemente no es simple debido a problemas de administración de memoria. Este hilo menciona el problema y sugiere una solución, pero es un lanzamiento previo a NDA y carece de código. Aquí hay un largo hilo que discute el problema sin dar una respuesta definitiva.

Aquí hay un código que he usado:

static NSString *CellIdentifier = @MyCellIdentifier;

MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
    cell = (MyCell *)[nib objectAtIndex:0];
}

Para usar este código, cree MyCell.m / .h, una nueva subclase de UITableViewCelly agregue IBOutletspara los componentes que desee. Luego crea un nuevo archivo Empty XIB. Abra el archivo Xib en IB, agregue un UITableViewCellobjeto, establezca su identificador en MyCellIdentifier y establezca su clase en MyCell y agregue sus componentes. Finalmente, conecta el IBOutletsa los componentes. Tenga en cuenta que no configuramos el propietario del archivo en IB.

Otros métodos recomiendan configurar el propietario del archivo y advertir de fugas de memoria si el Xib no se carga a través de una clase de fábrica adicional. Probé lo anterior en Instrumentos / Fugas y no vi pérdidas de memoria.

Entonces, ¿cuál es la forma canónica de cargar células de Xibs? ¿Establecemos el propietario del archivo? ¿Necesitamos una fábrica? Si es así, ¿cómo es el código para la fábrica? Si hay múltiples soluciones, aclaremos los pros y los contras de cada una de ellas ...

Publicado el 12/02/2009 a las 08:27
fuente por usuario
En otros idiomas...                            


23 respuestas

votos
292

La solución correcta es la siguiente:

- (void)viewDidLoad
{
 [super viewDidLoad];
 UINib *nib = [UINib nibWithNibName:@"ItemCell" bundle:nil];
 [[self tableView] registerNib:nib forCellReuseIdentifier:@"ItemCell"];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   // Create an instance of ItemCell
   PointsItemCell *cell =  [tableView dequeueReusableCellWithIdentifier:@"ItemCell"];

return cell;
}
Respondida el 29/11/2012 a las 16:57
fuente por usuario

votos
282

Aquí hay dos métodos que los estados originales de autor fue recomendado por un ingeniero IB .

Mira el mensaje real para más detalles. Yo prefiero el método # 2, ya que parece más simple.

Método 1:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Create a temporary UIViewController to instantiate the custom cell.
        UIViewController *temporaryController = [[UIViewController alloc] initWithNibName:@"BDCustomCell" bundle:nil];
        // Grab a pointer to the custom cell.
        cell = (BDCustomCell *)temporaryController.view;
        [[cell retain] autorelease];
        // Release the temporary UIViewController.
        [temporaryController release];
    }

    return cell;
}

Método # 2:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Load the top-level objects from the custom cell XIB.
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
        // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
        cell = [topLevelObjects objectAtIndex:0];
    }

    return cell;
}

Actualización (2014): Método # 2 sigue siendo válido, pero no hay documentación para más. Lo que solía ser en los documentos oficiales , pero ahora se elimina en favor de guiones gráficos.

He publicado un ejemplo de trabajo en Github:
https://github.com/bentford/NibTableCellExample

Respondida el 21/12/2009 a las 11:19
fuente por usuario

votos
33

Registro

Después de iOS 7, este proceso se ha simplificado hasta ( SWIFT 3.0 ):

// For registering nib files
tableView.register(UINib(nibName: "MyCell", bundle: Bundle.main), forCellReuseIdentifier: "cell")

// For registering classes
tableView.register(MyCellClass.self, forCellReuseIdentifier: "cell")

( Nota ) Esto también se puede lograr mediante la creación de las células en las .xibo .stroyboardlos archivos, como las células de prototipo. Si necesita adjuntar una clase de ellos, se puede seleccionar el prototipo de células y añadir la clase correspondiente (debe ser un descendiente de UITableViewCell, por supuesto).

Quitar de la cola

Y más tarde, quitado de la cola usando ( SWIFT 3.0 ):

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.textLabel?.text = "Hello"

    return cell
}

La diferencia es que este nuevo método no sólo Retiros de cola de la célula, sino que también crea si no existente (que significa que usted no tiene que hacer if (cell == nil)travesuras), y la célula está listo para usar al igual que en el ejemplo anterior.

( Advertencia ) tableView.dequeueReusableCell(withIdentifier:for:)tiene el nuevo comportamiento, si se llama a la otra (sin indexPath:) se obtiene el comportamiento anterior, en la que usted necesita para comprobar nile instancia usted mismo, se dio cuenta del UITableViewCell?valor de retorno.

if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? MyCellClass
{
    // Cell be casted properly
    cell.myCustomProperty = true
}
else
{
    // Wrong type? Wrong identifier?
}

Y, por supuesto, del tipo de la clase asociada de la célula es la que se define en el archivo .xib para la UITableViewCellsubclase, o, alternativamente, mediante el método de registro de otra.

Configuración

Lo ideal es que sus células han sido ya configurada en términos de apariencia y posicionamiento de contenido (como etiquetas y vistas de imágenes) en el momento en que éstos fueron registrados, y en el cellForRowAtIndexPathmétodo que simplemente rellenar.

Todos juntos

class MyCell : UITableViewCell
{
    // Can be either created manually, or loaded from a nib with prototypes
    @IBOutlet weak var labelSomething : UILabel? = nil
}

class MasterViewController: UITableViewController 
{
    var data = ["Hello", "World", "Kinda", "Cliche", "Though"]

    // Register
    override func viewDidLoad()
    {
        super.viewDidLoad()

        tableView.register(MyCell.self, forCellReuseIdentifier: "mycell")
        // or the nib alternative
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return data.count
    }

    // Dequeue
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "mycell", for: indexPath) as! MyCell

        cell.labelSomething?.text = data[indexPath.row]

        return cell
    }
}

Y, por supuesto, todo esto es disponible en ObjC con los mismos nombres.

Respondida el 21/05/2015 a las 01:47
fuente por usuario

votos
32

Tomó la respuesta de Shawn Craver y limpiado un poco.

BBCell.h:

#import <UIKit/UIKit.h>

@interface BBCell : UITableViewCell {
}

+ (BBCell *)cellFromNibNamed:(NSString *)nibName;

@end

BBCell.m:

#import "BBCell.h"

@implementation BBCell

+ (BBCell *)cellFromNibNamed:(NSString *)nibName {
    NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:NULL];
    NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
    BBCell *customCell = nil;
    NSObject* nibItem = nil;
    while ((nibItem = [nibEnumerator nextObject]) != nil) {
        if ([nibItem isKindOfClass:[BBCell class]]) {
            customCell = (BBCell *)nibItem;
            break; // we have a winner
        }
    }
    return customCell;
}

@end

Hago todas las subclases de BBCell de mi UITableViewCell, y luego vuelva a colocar la norma

cell = [[[BBDetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BBDetailCell"] autorelease];

con:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
Respondida el 22/06/2010 a las 03:15
fuente por usuario

votos
15

Solía del bentford Método # 2 :

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Load the top-level objects from the custom cell XIB.
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
        // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
        cell = [topLevelObjects objectAtIndex:0];
    }

    return cell;
}

Funciona, pero cuidado con las conexiones a del propietario del archivo en su archivo personalizado de UITableViewCell .xib.

Con la aprobación owner:selfen su loadNibNameddeclaración, se establece el UITableViewControllercomo el dueño del Archivo de la UITableViewCell.

Si arrastra y suelta en el fichero de cabecera en el IB para establecer acciones y puntos de venta, será configurarlas como el propietario del archivo por defecto.

En loadNibNamed:owner:options, el código de Apple tratará de establecer las propiedades de su UITableViewController, ya que es el propietario. Pero usted no tiene esas propiedades que se definen, por lo que se obtiene un error de ser valor de la clave de codificación compatible con :

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason:     '[<MyUITableViewController 0x6a383b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key myLabel.'

Si un evento se desencadena en su lugar, obtendrá un NSInvalidArgumentException:

-[MyUITableViewController switchValueDidChange:]: unrecognized selector sent to instance 0x8e9acd0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyUITableViewController switchValueDidChange:]: unrecognized selector sent to instance 0x8e9acd0'
*** First throw call stack:
(0x1903052 0x15eed0a 0x1904ced 0x1869f00 0x1869ce2 0x1904ec9 0x5885c2 0x58855a 0x62db76 0x62e03f 0x77fa6c 0x24e86d 0x18d7966 0x18d7407 0x183a7c0 0x1839db4 0x1839ccb 0x1f8b879 0x1f8b93e 0x585a9b 0xb904d 0x2c75)
terminate called throwing an exceptionCurrent language:  auto; currently objective-c

Una solución fácil es señalar las conexiones Interface Builder en el UITableViewCellpropietario del lugar de Archivo:

  1. Haz clic derecho sobre el archivo de propietario para tirar de la lista de conexiones
  2. Tomar una captura de pantalla con Comando-Shift-4 (arrastre para seleccionar el área a ser capturado)
  3. x cabo las conexiones del propietario del archivo
  4. Haga clic derecho en el UITableCell en la jerarquía de objetos y volver a agregar las conexiones.
Respondida el 19/03/2012 a las 22:41
fuente por usuario

votos
12

Me he decidido a publicar, ya que no me gusta ninguna de estas respuestas - las cosas siempre pueden ser más sencilla y esto es, con mucho, la forma más concisa que he encontrado.

1. Construir su Xib en Interface Builder a su gusto

  • Establecer propietario del archivo de clase NSObject
  • Añadir un UITableViewCell y establecer su clase con el MyTableViewCellSubclass - si se bloquea IB (que ocurre en Xcode> 4 partir de este escrito), sólo tiene que utilizar un UIView de hacer la interfaz en Xcode 4 si todavía lo tienes por ahí
  • La disposición de su subvistas dentro de esta célula y se unen sus conexiones IBOutlet a su @interface en el .h o .m (.m es mi preferencia)

2. En la subclase UIViewController o UITableViewController

@implementation ViewController

static NSString *cellIdentifier = @"MyCellIdentier";

- (void) viewDidLoad {

    ...
    [self.tableView registerNib:[UINib nibWithNibName:@"MyTableViewCellSubclass" bundle:nil] forCellReuseIdentifier:cellIdentifier];
}

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCellSubclass *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    ...

    return cell;
}

3. En sus MyTableViewCellSubclass

- (id) initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        ...
    }

    return self;
}
Respondida el 26/08/2013 a las 09:18
fuente por usuario

votos
8

Si está usando el Interface Builder para crear células, compruebe que ha configurado el identificador en el Inspector. A continuación, compruebe que es el mismo al llamar dequeueReusableCellWithIdentifier.

Accidentalmente se olvidó de establecer algunos identificadores en un proyecto de tabla-pesado, y el cambio en el rendimiento era como la noche y el día.

Respondida el 28/04/2010 a las 11:55
fuente por usuario

votos
7

Cargar UITableViewCells desde XIB ahorra una gran cantidad de código, pero generalmente da como resultado una velocidad de desplazamiento horrible (en realidad, no es el XIB sino el uso excesivo de UIViews el que causa esto).

Te sugiero que le eches un vistazo a esto: referencia del enlace

Respondida el 12/02/2009 a las 15:19
fuente por usuario

votos
5

Este es el método de clase que he estado usando para crear celdas personalizadas a partir de XIB:

+ (CustomCell*) createNewCustomCellFromNib {

    NSArray* nibContents = [[NSBundle mainBundle]
                            loadNibNamed:@"CustomCell" owner:self options:NULL];

    NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
    CustomCell *customCell= nil;
    NSObject* nibItem = nil;

    while ( (nibItem = [nibEnumerator nextObject]) != nil) {

        if ( [nibItem isKindOfClass: [CustomCell class]]) {
            customCell = (CustomCell*) nibItem;

            if ([customCell.reuseIdentifier isEqualToString: @"CustomCell"]) {
                break; // we have a winner
            }
            else
                fuelEntryCell = nil;
        }
    }
    return customCell;
}

Luego, en el XIB, configuro el nombre de clase y reutilizo el identificador. Después de eso, puedo llamar a ese método en mi controlador de vista en lugar de

[[UITableViewCell] alloc] initWithFrame:]

Es lo suficientemente rápido y se usa en dos de mis aplicaciones de envío. Es más confiable que llamar [nib objectAtIndex:0]y, en mi opinión, al menos, más confiable que el ejemplo de Stephan Burlot, porque está garantizado que solo obtendrá una vista de un XIB que sea del tipo correcto.

Respondida el 12/02/2009 a las 14:47
fuente por usuario

votos
4

Solución correcta es esta

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"CustomCell"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell  *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
    return cell; 
    }
Respondida el 07/09/2016 a las 05:33
fuente por usuario

votos
3

Mira esto - http://eppz.eu/blog/custom-uitableview-cell/ - forma muy conveniente usando una clase pequeña que termina una línea en la implementación del controlador:

-(UITableViewCell*)tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
    return [TCItemCell cellForTableView:tableView
                          atIndexPath:indexPath
                      withModelSource:self];
}

introducir descripción de la imagen aquí

Respondida el 09/07/2013 a las 10:18
fuente por usuario

votos
3

Volver a cargar la SEMILLA es caro. Mejor para cargarlo una vez, luego instanciar los objetos cuando se necesita una célula. Tenga en cuenta que puede agregar UIImageViews etc a la punta, incluso varias células, utilizando este método (de Apple "registerNIB" IOS5 permite sólo un objeto de alto nivel - Bug 10580062 "IOS5 tableView registerNib: excesivamente restrictivo"

Así que mi código es abajo - se lee en la SEMILLA una vez (en initialize como lo hice o en viewDidLoad -.. Todo lo partir de entonces, se ejemplariza la punta en objetos a continuación, elegir el que necesita Esto es mucho más eficiente que la carga de la punta una y otra vez.

static UINib *cellNib;

+ (void)initialize
{
    if(self == [ImageManager class]) {
        cellNib = [UINib nibWithNibName:@"ImageManagerCell" bundle:nil];
        assert(cellNib);
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"TheCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if(cell == nil) {
        NSArray *topLevelItems = [cellNib instantiateWithOwner:nil options:nil];
        NSUInteger idx = [topLevelItems indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop)
                            {
                                UITableViewCell *cell = (UITableViewCell *)obj;
                                return [cell isKindOfClass:[UITableViewCell class]] && [cell.reuseIdentifier isEqualToString:cellID];
                            } ];
        assert(idx != NSNotFound);
        cell = [topLevelItems objectAtIndex:idx];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"Howdie %d", indexPath.row];

    return cell;
}
Respondida el 14/12/2011 a las 20:01
fuente por usuario

votos
2

En primer lugar importar el archivo de celda personalizado #import "CustomCell.h"y luego cambiar el método de delegado como se menciona a continuación:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *simpleTableIdentifier = @"CustomCell";

CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    cell = [nib objectAtIndex:0];

    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}         

     return cell;
}
Respondida el 26/02/2014 a las 07:48
fuente por usuario

votos
2

La forma correcta de hacerlo es crear una subclase UITableViewCell aplicación, encabezado y XI ter. En el XI ter quitar cualquier vista y sólo tiene que añadir una celda de tabla. Establecer la clase como el nombre de la subclase UITableViewCell. Para el propietario del fichero, que sea el nombre de la clase subclase UITableViewController. Conectar el propietario del archivo a la célula utilizando la salida tableViewCell.

En el archivo de cabecera:

UITableViewCell *_tableViewCell;
@property (assign) IBOutlet UITableViewCell *tableViewCell;

En el archivo de implementación:

@synthesize tableViewCell = _tableViewCell;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *kCellIdentifier = @"reusableCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:kCellIdentifier owner:self options:nil];
        cell = _tableViewCell;
        self.tableViewCell = nil;
    }

    return cell;
}
Respondida el 28/06/2012 a las 22:57
fuente por usuario

votos
2

Lo que hago para esto es declarar una IBOutlet UITableViewCell *cellen tu clase de controlador. Luego invoque el NSBundle loadNibNamedmétodo de clase, que alimentará UITableViewCella la celda declarada anteriormente.

Para el xib, crearé un xib vacío y agregaré el UITableViewCellobjeto en IB, donde se puede configurar según sea necesario. Esta vista luego se conecta a la celda IBOutleten la clase de controlador.

- (UITableViewCell *)tableView:(UITableView *)table
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%@ loading RTEditableCell.xib", [self description] );

    static NSString *MyIdentifier = @"editableCellIdentifier";
    cell = [table dequeueReusableCellWithIdentifier:MyIdentifier];

    if(cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"RTEditableCell"
                                      owner:self
                                    options:nil];
    }

    return cell;
}

NSBundle agrega loadNibNamed (inicio de sesión de ADC)

Artículo de cocoawithlove.com. Obtuve el concepto desde (obtenga la aplicación de muestra de números de teléfono).

Respondida el 12/02/2009 a las 19:01
fuente por usuario

votos
1

En Swift 4,2 y Xcode 10

Tengo tres archivos de células XIB

en viewDidLoad registrar sus archivos XIB como este ...

Este es el primer enfoque

tableView.register(UINib.init(nibName: "XIBCell", bundle: nil), forCellReuseIdentifier: "cell1")
tableView.register(UINib.init(nibName: "XIBCell2", bundle: nil), forCellReuseIdentifier: "cell2")
//tableView.register(UINib.init(nibName: "XIBCell3", bundle: nil), forCellReuseIdentifier: "cell3")

Segundo enfoque se registra directamente los archivos XIB en cellForRowAt indexPath:

Se trata de mis funciones de delegado tableview

//MARK: - Tableview delegates
override func numberOfSections(in tableView: UITableView) -> Int {

    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return 6
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //This is first approach
    if indexPath.row == 0 {//Load first XIB cell
        let placeCell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! XIBCell
        return placeCell
    //Second approach
    } else if indexPath.row == 5 {//Load XIB cell3
        var cell = tableView.dequeueReusableCell(withIdentifier:"cell3") as? XIBCell3
        if cell == nil{
            let arrNib:Array = Bundle.main.loadNibNamed("XIBCell3",owner: self, options: nil)!
            cell = arrNib.first as? XIBCell3
        }

        //ADD action to XIB cell button
        cell?.btn.tag = indexPath.row//Add tag to button
        cell?.btn.addTarget(self, action: #selector(self.bookbtn1(_:)), for: .touchUpInside);//selector

        return cell!
    //This is first approach
    } else {//Load XIB cell2
        let placeCell = tableView.dequeueReusableCell(withIdentifier: "cell2") as! XIBCell2

        return placeCell
    }

}
Respondida el 12/10/2018 a las 07:02
fuente por usuario

votos
1
  1. Crear su propia clase personalizada AbcViewCellsubclase de UITableViewCell(Asegúrese de que el nombre de archivo de la clase y el nombre de archivo de la semilla son los mismos)

  2. Cree este método de clase de extensión.

    extension UITableViewCell {
        class func fromNib<T : UITableViewCell>() -> T {
            return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)?[0] as! T
        }
    }
    
  3. Usarlo.

    let cell: AbcViewCell = UITableViewCell.fromNib()

Respondida el 07/09/2017 a las 01:07
fuente por usuario

votos
1

No sé si hay una manera canónica, pero este es mi método:

  • Crea un xib para un ViewController
  • Establezca la clase Propietario de archivo en UIViewController
  • Eliminar la vista y agregar una UITableViewCell
  • Establezca la clase de su UITableViewCell en su clase personalizada
  • Establezca el Identificador de su UITableViewCell
  • Establezca la salida de su vista de controlador de vista a su UITableViewCell

Y usa este código:

MyCustomViewCell *cell = (MyCustomViewCell *)[_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
  UIViewController* c = [[UIViewController alloc] initWithNibName:CellIdentifier bundle:nil];
  cell = (MyCustomViewCell *)c.view;
  [c release];
}

En tu ejemplo, usando

[nib objectAtIndex:0]

puede romperse si Apple cambia el orden de los elementos en el xib.

Respondida el 12/02/2009 a las 10:03
fuente por usuario

votos
0
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

            let cellReuseIdentifier = "collabCell"
            var cell:collabCell! = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as? collabCell
            if cell == nil {
                tableView.register(UINib(nibName: "collabCell", bundle: nil), forCellReuseIdentifier: cellReuseIdentifier)
                cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! collabCell!
            }


            return cell

}
Respondida el 18/05/2018 a las 08:17
fuente por usuario

votos
0

Aquí es un enfoque universal para el registro de las células en UITableView:

protocol Reusable {
    static var reuseID: String { get }
}

extension Reusable {
    static var reuseID: String {
        return String(describing: self)
    }
}

extension UITableViewCell: Reusable { }

extension UITableView {

func register<T: UITableViewCell>(cellClass: T.Type = T.self) {
    let bundle = Bundle(for: cellClass.self)
    if bundle.path(forResource: cellClass.reuseID, ofType: "nib") != nil {
        let nib = UINib(nibName: cellClass.reuseID, bundle: bundle)
        register(nib, forCellReuseIdentifier: cellClass.reuseID)
    } else {
        register(cellClass.self, forCellReuseIdentifier: cellClass.reuseID)
    }
}

Explicación:

  1. Reusableprotocolo genera ID de célula a partir de su nombre de la clase. Asegúrese de seguir la convención:cell ID == class name == nib name .
  2. UITableViewCellse ajusta a Reusableprotocolo.
  3. UITableView extensión abstrae la diferencia en el registro de células a través de la semilla o clase.

Ejemplo de uso:

override func viewDidLoad() {
    super.viewDidLoad()
    let tableView = UITableView()
    let cellClasses: [UITableViewCell.Type] = [PostCell.self, ProfileCell.self, CommentCell.self]
    cellClasses.forEach(tableView.register)
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: PostCell.self.reuseID) as? PostCell
    ...
    return cell
}
Respondida el 18/08/2017 a las 05:08
fuente por usuario

votos
0

Esta extensión requiere Xcode7 beta6

extension NSBundle {
    enum LoadViewError: ErrorType {
        case ExpectedXibToExistButGotNil
        case ExpectedXibToContainJustOneButGotDifferentNumberOfObjects
        case XibReturnedWrongType
    }

    func loadView<T>(name: String) throws -> T {
        let topLevelObjects: [AnyObject]! = loadNibNamed(name, owner: self, options: nil)
        if topLevelObjects == nil {
            throw LoadViewError.ExpectedXibToExistButGotNil
        }
        if topLevelObjects.count != 1 {
            throw LoadViewError.ExpectedXibToContainJustOneButGotDifferentNumberOfObjects
        }
        let firstObject: AnyObject! = topLevelObjects.first
        guard let result = firstObject as? T else {
            throw LoadViewError.XibReturnedWrongType
        }
        return result
    }
}

Crear un archivo Xib que contiene sólo 1 UITableViewCell personalizada.

Cárgalo.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
Respondida el 28/08/2015 a las 19:44
fuente por usuario

votos
0
 NSString *CellIdentifier = [NSString stringWithFormat:@"cell %ld %ld",(long)indexPath.row,(long)indexPath.section];


    NewsFeedCell *cell = (NewsFeedCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    cell=nil;

    if (cell == nil)
    {
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewsFeedCell" owner:nil options:nil];

        for(id currentObject in topLevelObjects)
        {
            if([currentObject isKindOfClass:[NewsFeedCell class]])
            {
                cell = (NewsFeedCell *)currentObject;
                break;
            }
        }
}
return cell;
Respondida el 11/06/2014 a las 07:38
fuente por usuario

votos
0

Aquí está mi método para que: Cargando UITableViewCells personalizada de archivos XI ter ... Sin embargo, otro método

La idea es crear una subclase de la SampleCell UITableViewCellcon una IBOutlet UIView *contentpropiedad y una propiedad para cada encargo subvista necesita configurar a partir del código. A continuación, para crear un archivo SampleCell.xib. En este archivo semilla, cambiar el propietario del archivo a SampleCell. Añadir un contenido de UIViewtamaño para adaptarse a sus necesidades. Agregar y configurar todos los subvistas (etiqueta, vistas de imágenes, botones, etc) que desea. Por último, vincular la vista de contenido y los subvistas al propietario del archivo.

Respondida el 24/03/2011 a las 12:51
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more