¿Cómo se puede obtener el tamaño de diseño automático de las UICollectionViewCells en iOS 8? (systemLayoutSizeFittingSize devuelve el tamaño con cero altura en iOS 8)


Desde iOS 8 [UIColletionViewCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] devuelve un tamaño con altura de 0.

Esto es lo que hace el código:

Para determinar el tamaño de la celda en un UICollectionView en iOS 7 uso systemLayoutSizeFittingSize: en una celda definida en un archivo xib usando diseño automático. El tamaño depende del tamaño de fuente de un UILabel que es una subview del UICollectionViewCell en mi archivo xib. La fuente de la etiqueta se establece en UIFontTextStyleBody. Así que básicamente el tamaño de la celda depende de la configuración de tamaño de fuente hecha en iOS 7.

Aquí está el código en sí mismo:

+ (CGSize)cellSize {
    UINib *nib = [UINib nibWithNibName:NSStringFromClass([MyCollectionViewCell class]) bundle:nil];

    // Assumption: The XIB file only contains a single root UIView.
    UIView *rootView = [[nib instantiateWithOwner:nil options:nil] lastObject];

    if ([rootView isKindOfClass:[MyCollectionViewCell class]]) {
        MyCollectionViewCell *sampleCell = (MyCollectionViewCell*)rootView;
        sampleCell.label.text = @"foo"; // sample text without bar

        [sampleCell setNeedsLayout];
        [sampleCell layoutIfNeeded];

        return [sampleCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    }

    return CGSizeZero;

}

Funciona perfectamente bien en iOS 7, pero no en iOS 8. Desafortunadamente no tengo idea de por qué.

¿Cómo puedo obtener el tamaño de diseño automático de las UICollectionViewCells en iOS 8?

PS: Usando

 return [sampleCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

En lugar de

 return [sampleCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

Como alguien podría sugerir, no hace ninguna diferencia.

Author: Philip McDermott, 2014-08-12

8 answers

Se parece a esto oficialmente un error: Presenté un informe que se cerró como un duplicado de este

Se informará cuando salga la Beta 6.

[Actualizar : funciona correctamente en la semilla GM de iOS 8, y el error ha sido cerrado por Apple.]

 7
Author: Philip McDermott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-22 15:16:23

Lo que necesita hacer es envolver todo su contenido en una vista de contenedor, luego llame a:

return [sampleCell.containerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

Su celda debería tener este aspecto: cell -> containerView -> sub views

Esto funciona tanto en ios7 como en ios8.

Supuestamente en ios8, todo lo que tiene que hacer es establecer el estimateSize & cell automáticamente se auto tamaño por su cuenta. Aparentemente eso no está funcionando a partir de beta 6.

 8
Author: Triet Luong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-30 19:21:45

Estamos usando una solución alternativa por ahora, copiada a continuación. Con suerte, estos problemas se resolverán antes del lanzamiento de iOS 8 y podemos eliminar esto. (El kludge asume el conocimiento del comportamiento implícito de Apple contentView, y tenemos que hackear las referencias de IB outlet a cualquier restricción que transfiramos.)

Notamos que también están eliminando todas las máscaras de autoresizing de storyboards / NIBs durante la actualización, lo que tiene sentido dado que se supone que es auto-layout, pero las vistas de colección aún se remontan a springs & puntal. Tal vez esto ha sido pasado por alto en la purga?

Dan Dan

/**
 Kludge around cell sizing issues for iOS 8 and deployment to iOS 7 when compiled for 8.  Call this on the collection view cell before it is used, such as in awakeFromNib.  Because this manipulates top-level constraints, any references to such initial constraints, such as from IB outlets, will be invalidated.

 Issue 1: As of iOS 8 Beta 5, systemLayoutSizeFittingSize returns height 0 for a UICollectionViewCell.  In IB, cells have an implicit contentView, below which views placed in IB as subviews of the cell are actually placed.  However, constraints set between these subviews and its superview are placed on the cell, rather than the contentView (which is their actual superview).  This should be OK, as a constraint among items may be placed on any common ancestor of those items, but this is not playing nice with systemLayoutSizeFittingSize.  Transferring those constraints to be on the contentView seems to fix the issue.

 Issue 2: In iOS 7, prior to compiling against iOS 8, the resizing mask of the content view was being set by iOS to width+height.  When running on iOS 7 compiled against iOS 8 Beta 5, the resizing mask is None, resulting in constraints effecting springs for the right/bottom margins.  Though this starts out the contentView the same size as the cell, changing the cell size, as we do in the revealing list, is not tracked by changing it's content view.  Restore the previous behavior.

 Moving to dynamic cell sizing in iOS 8 may circumvent this issue, but that remedy isn't available in iOS 7.
*/
+ (void)kludgeAroundIOS8CollectionViewCellSizingIssues:(UICollectionViewCell *)cell {

    // transfer constraints involving descendants on cell to contentView
    UIView *contentView = cell.contentView;
    NSArray *cellConstraints = [cell constraints];
    for (NSLayoutConstraint *cellConstraint in cellConstraints) {
        if (cellConstraint.firstItem == cell && cellConstraint.secondItem) {
            NSLayoutConstraint *parallelConstraint = [NSLayoutConstraint constraintWithItem:contentView attribute:cellConstraint.firstAttribute relatedBy:cellConstraint.relation toItem:cellConstraint.secondItem attribute:cellConstraint.secondAttribute multiplier:cellConstraint.multiplier constant:cellConstraint.constant];
            parallelConstraint.priority = cellConstraint.priority;
            [cell removeConstraint:cellConstraint];
            [contentView addConstraint:parallelConstraint];
        } else if (cellConstraint.secondItem == cell && cellConstraint.firstItem) {
            NSLayoutConstraint *parallelConstraint = [NSLayoutConstraint constraintWithItem:cellConstraint.firstItem attribute:cellConstraint.firstAttribute relatedBy:cellConstraint.relation toItem:contentView attribute:cellConstraint.secondAttribute multiplier:cellConstraint.multiplier constant:cellConstraint.constant];
            parallelConstraint.priority = cellConstraint.priority;
            [cell removeConstraint:cellConstraint];
            [contentView addConstraint:parallelConstraint];
        }
    }

    // restore auto-resizing mask to iOS 7 behavior
    contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];
}
 4
Author: PlayfulGeek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-29 17:01:45

Este es un error en xCode6 y iOS 8 SDK que se ejecuta en dispositivos iOS7 :) Casi me agota el día. Finalmente trabajó con el siguiente código en la subclase UICollectionViewCell. Espero que esto se solucione con la próxima versión

- (void)setBounds:(CGRect)bounds {
    [super setBounds:bounds];
    self.contentView.frame = bounds;
}
 0
Author: Krishna Kishore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-01 20:53:11

Tuve el mismo problema para UITableViewCells y iOS 7 (ios8 funciona perfectamente), pero la solución" Triet Luong"funcionó para mí:

return [sampleCell.containerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
 0
Author: Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-11 17:32:17

Esto no es un error, he estado lidiando con este problema desde hace algún tiempo y he intentado cosas diferentes, estoy dando a continuación los pasos que ha funcionado para mí:

1) utilice contentView [sampleCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

2) puede crear su propio contentView y agregar las subViews al contentView, no olvide fijar la parte superior, inferior e izquierda y derecha del contentView si está utilizando un contentView personalizado al SuperView, si usted no hace esto entonces altura será 0, aquí también dependiendo de sus requisitos usted puede para. por ejemplo, no fijar la parte inferior del contentView al SuperView para que la altura de la vista pueda variar, pero fijar es importante y fijar cuál depende de sus requisitos.

3) establezca las restricciones correctamente en interface builder dependiendo de sus requisitos, hay ciertas restricciones que no se pueden agregar en interface builder, pero luego puede agregarlas en viewDidLoad del ViewController.

Así que mi entrada de 2 centavos es que las restricciones deben configurarse correctamente en el creador de interfaces para systemLayoutSizeFittingSize:UILayoutFittingCompressedSize para devolver las dimensiones correctas, esta es la solución chicos.

 0
Author: Sam Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-03 20:35:07

Tal vez tenga alguna restricción incorrecta, debe especificar tanto el espacio superior virtical como el espacio inferior entre su UIView y contentView, también tuve este problema antes, eso es porque acabo de especificar el espacio superior virtical, y no especificé el espacio inferior virtical a contentView

 0
Author: Gene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-28 05:28:50

Fue un error en las versiones beta de iOS 8. Finalmente se soluciona con para iOS 8 GB (Build 12A365). Así que para mí ahora funciona con el mismo código que escribí para iOS 7. (ver la pregunta)

 -1
Author: martn_st,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-12 09:44:21