Cuando el uso de «Prototipos Dinámicos» para especificar UITableView contenido en el guión gráfico, hay un «alto de Fila» de la propiedad que se puede establecer Personalizado.

Al crear instancias de las células, esta costumbre la altura de la fila no es tomado en cuenta. Esto tiene sentido, ya que el prototipo de celda que yo uso es decidido por mi código de la aplicación en el momento de la celda se crea una instancia. Para crear una instancia de todas las células a la hora de calcular el diseño de introducir una penalización de rendimiento, por lo que entiendo la razón por la que no se puede hacer.

Entonces la pregunta, ¿hay algún modo de recuperar la altura dada una celda de reutilización de identificador, por ejemplo,

[myTableView heightForCellWithReuseIdentifier:@"MyCellPrototype"];

o algo a lo largo de esa línea? O tengo que duplicar el explícito el alto de la fila en mi código de la aplicación, con la carga de mantenimiento que sigue?

Resuelto, con la ayuda de @TimothyMoose:

Las alturas se almacenan en las células mismas, lo que significa que la única manera de llegar a las alturas es instanciar los prototipos. Una forma de hacer esto es la pre-eliminar de la cola de las células fuera de la célula normal método de devolución de llamada. Aquí está mi pequeño POC, que trabaja:

#import "ViewController.h"

@interface ViewController () {
    NSDictionary* heights;
}
@end

@implementation ViewController

- (NSString*) _reusableIdentifierForIndexPath:(NSIndexPath *)indexPath
{
    return [NSString stringWithFormat:@"C%d", indexPath.row];
}

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(!heights) {
        NSMutableDictionary* hts = [NSMutableDictionary dictionary];
        for(NSString* reusableIdentifier in [NSArray arrayWithObjects:@"C0", @"C1", @"C2", nil]) {
            CGFloat height = [[tableView dequeueReusableCellWithIdentifier:reusableIdentifier] bounds].size.height;
            hts[reusableIdentifier] = [NSNumber numberWithFloat:height];
        }
        heights = [hts copy];
    }
    NSString* prototype = [self _reusableIdentifierForIndexPath:indexPath];
    return [heights[prototype] floatValue];
}

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 3;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString* prototype = [self _reusableIdentifierForIndexPath:indexPath];
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:prototype];
    return cell;
}

@end
  • Yo había estado usando este método durante un tiempo, a continuación, en un nuevo guión, me estaba poniendo en su mayoría cero-altura (altura y ancho) dimensiones de las celdas. Incluso el cero fueron los valores inesperados. La desactivación de las clases de talla restaurada, esta funcionalidad. Decepcionante, sin embargo, ya que este «fix» deshabilita la funcionalidad importante en el guión gráfico. Sin embargo, esto funcionó para mi necesidad inmediata.
  • He encontrado una solución más completa para la solución de este problema con el tamaño de las clases habilitado.
InformationsquelleAutor Krumelur | 2012-12-01

2 Comentarios

  1. 28

    Para estáticas (sin data-driven) de altura, sólo se puede quitar de la cola de la célula una vez y almacenar la altura:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSNumber *height;
        if (!height) {
            UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyCustomCell"];
            height = @(cell.bounds.size.height);
        }
        return [height floatValue];
    }

    Dinámico (data-driven) de altura, se puede almacenar un prototipo de celda de la vista y controlador de añadir un método a la celda de la clase en el que se calcula la altura, teniendo en cuenta el contenido por defecto del prototipo instancia, como subvista colocación, fuentes, etc.:

    - (MyCustomCell *)prototypeCell
    {
        if (!_prototypeCell) {
            _prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:@"MyCustomCell"];
        }
        return _prototypeCell;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        //Data for the cell, e.g. text for label
        id myData = [self myDataForIndexPath:indexPath];
    
        //Prototype knows how to calculate its height for the given data
        return [self.prototypeCell myHeightForData:myData];
    }

    Por supuesto, si usted está utilizando la altura de encargo, usted probablemente tiene varios prototipos de celulares, así que se podría almacenar en un diccionario o algo.

    Medida de lo que puedo decir, la vista de la tabla no intente volver a utilizar el prototipo, presumiblemente porque era descargados fuera de cellForRowAtIndexPath:. Este enfoque ha funcionado muy bien para nosotros, porque permite al diseñador para modificar las células de los diseños en el guión gráfico sin necesidad de cambios en el código.

    Edición: aclarado el significado de código de muestra y se añadió un ejemplo para el caso de la altura estática.

    • No reconozco a la heightForData: método. ¿Qué hacer?
    • heightForData: es un método que iba a escribir para calcular la altura de la celda de datos.
    • Lo que yo veo. El problema es que quiero usar la altura almacenados en el archivo de guión gráfico en sí (una altura estática). Antes de sacarlo de la cola de las células de trabajo para que aunque. Voy a probarlo.
    • Funciona. Gracias! Voy a actualizar a la pregunta con la solución completa para ayudar a los demás.
    • Sí, mi edición tiene un ejemplo de la altura estática así.
    • Echa un vistazo a TLIndexPathTools. Calcula el alto de celda mediante la creación automática de prototipo y un) devolución de los prototipos de la altura estática o, b) si la celda implementa la TLDynamicSizeView prototipo, volviendo a la dinámica de altura. Consulte la Dinámico de Altura proyecto de ejemplo. Esto es realmente una característica secundaria de la biblioteca, pero es digno de la comprobación hacia fuera.
    • El problema con este enfoque es que no funciona cuando tu interfaz de los cambios de orientación de Vertical a horizontal. Posible solución: Restablecer la estructura de la anchura de la celda de la tabla de ancho, antes de calcular la altura en heightForRowAtIndexPath: método. Espero que esto ayude.

  2. 5

    He creado una categoría para UITableView hace un tiempo que puede llegar útil para esto. Almacena ‘prototipo’ de las células utilizando relacionar objetos para la reutilización de los prototipos y proporciona una comodidad método para la obtención de la altura de la fila asignada en el guión gráfico. Los prototipos son liberados cuando la vista de la tabla se cancela la asignación.

    UITableView+PrototypeCells.h

    #import <UIKit/UIKit.h>
    
    @interface UITableView (PrototypeCells)
    
    - (CGFloat)heightForRowWithReuseIdentifier:(NSString*)reuseIdentifier;
    - (UITableViewCell*)prototypeCellWithReuseIdentifier:(NSString*)reuseIdentifier;
    
    @end

    UITableView+PrototypeCells.m

    #import "UITableView+PrototypeCells.h"
    #import <objc/runtime.h>
    
    static char const * const key = "prototypeCells";
    
    @implementation UITableView (PrototypeCells)
    - (void)setPrototypeCells:(NSMutableDictionary *)prototypeCells {
        objc_setAssociatedObject(self, key, prototypeCells, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (NSMutableDictionary *)prototypeCells {
        return objc_getAssociatedObject(self, key);
    }
    
    - (CGFloat)heightForRowWithReuseIdentifier:(NSString*)reuseIdentifier {
        return [self prototypeCellWithReuseIdentifier:reuseIdentifier].frame.size.height;
    }
    
    - (UITableViewCell*)prototypeCellWithReuseIdentifier:(NSString*)reuseIdentifier {
        if (self.prototypeCells == nil) {
            self.prototypeCells = [[NSMutableDictionary alloc] init];
        }
    
        UITableViewCell* cell = self.prototypeCells[reuseIdentifier];
        if (cell == nil) {
            cell = [self dequeueReusableCellWithIdentifier:reuseIdentifier];
            self.prototypeCells[reuseIdentifier] = cell;
        }
        return cell;
    }
    
    @end

    Uso

    La obtención de la altura estática establecido en el guión es tan simple como esto:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        return [tableView heightForRowWithReuseIdentifier:@"cellIdentifier"];
    }

    Suponiendo un multi-sección de la vista de tabla:

    enum {
        kFirstSection = 0,
        kSecondSection
    };
    
    static NSString* const kFirstSectionRowId = @"section1Id";
    static NSString* const kSecondSectionRowId = @"section2Id";
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        CGFloat height = tableView.rowHeight; //Default UITableView row height
        switch (indexPath.section) {
            case kFirstSection:
                height = [tableView heightForRowWithReuseIdentifier:kFirstSectionRowId];
                break;
            case kSecondSection:
                height = [tableView heightForRowWithReuseIdentifier:kSecondSectionRowId];
        }
        return height;
    }

    Y, finalmente, si la altura de la fila es dinámica:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        id thisRowData = self.allData[indexPath.row]; //Obtain the data for this row
    
        //Obtain the prototype cell
        MyTableViewCell* cell = (MyTableViewCell*)[self prototypeCellWithReuseIdentifier:@"cellIdentifier"];
    
        //Ask the prototype cell for its own height when showing the specified data
        return [cell heightForData:thisRowData];
    }
    • Esto parece realmente útil. Gracias!
    • Gran aplicación, usted debe poner que en github & pot

Dejar respuesta

Please enter your comment!
Please enter your name here