Estamos utilizando un UICollectionView para mostrar células que cubren la totalidad de la pantalla (menos el estado y la barra de navegación). El tamaño de la celda se establece a partir de self.collectionView.bounds.size:

- (void)viewWillAppear:(BOOL)animated
{
    //
    //value isn't correct with the top bars until here
    //
    CGSize tmpSize = self.collectionView.bounds.size;
    _currentCellSize = CGSizeMake( (tmpSize.width), (tmpSize.height));
}

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout*)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    return _currentCellSize;
}

Esto establece el tamaño correcto para cada dispositivo. Cada célula se define no tener inserciones, y el diseño no tiene ningún encabezado o pie de página. Sin embargo, cuando lo hacemos girar, de vertical a horizontal se obtiene el siguiente «queja»:

the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.

Ahora entiendo este error, sin embargo, nos restablecer el tamaño de la celda y utilizar el flujo de diseños construido en la rotación de la transición:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    //self.collectionView.bounds are still the last size...not the new size here
}
- (void)didRotateFromInterfaceOrientation: UIInterfaceOrientation)fromInterfaceOrientation
{
    CGSize tmpSize = self.collectionView.bounds.size;
    _currentCellSize = CGSizeMake( (tmpSize.width), (tmpSize.height));
    [self.collectionView performBatchUpdates:nil completion:nil];//this will force the redraw/size of the cells.
}

Las células se reproducen correctamente en el paisaje.

Parece como si el Flujo de Diseño se ve el antiguo tamaño de la célula (lo que provoca la queja, ya será demasiado alto), pero no de lectura/render el nuevo tamaño de celda configurado en didRotateFromInterfaceOrientation.

Hay una manera de deshacerse de la queja?

Hemos tratado de encontrar otro gancho durante un dispositivo de girar la transición que tiene acceso al destino correcto tamaño de la pantalla (vs el actual tamaño de la pantalla) no hubo suerte. La salida de depuración muestra la queja que sucede después de willRotateToInterfaceOrientation pero antes de didRotateFromInterfaceOrientation.

También hemos comprobado la obvia; si establecemos la altura de la celda para ser de un tamaño fijo menor que el paisaje de la altura de la pantalla, la queja no se produce. También, la queja no se produce cuando la rotación de paisaje a retrato.

Todo corre bien, y hace correctamente. Sin embargo, esta queja nos preocupa. Alguien más tiene alguna idea o solución?

  • Tengo un poco más compleja de diseño que se han descrito aquí, con anidada collectionView células. Sin embargo, el problema que yo veo es esencialmente idéntica. Tengo una subclase a la disposición de flujo y poner un punto de interrupción en el proceso de preparación de método de diseño de la subclase. El mensaje de error aparece cuando me gire para paisaje antes de preparar el diseño, incluso ha sido llamado. Tan lejos como soy consciente de que esta es la primera forma de gancho en el diseño de la vista de colección. Probablemente no ayudan mucho a alguien pero sabes que tu no solo en la obtención de este problema.
  • Nelson Siempre encontrar una manera de arreglar la advertencia?
  • no. el pez más grande para freír, hemos decidido vivir con esto por ahora.
  • Solución disponible aquí: stackoverflow.com/questions/16341778/…
  • Agradezco todas las respuestas aquí. Voy a evaluar cuando tengo un descanso en nuestra línea de tiempo del proyecto.
  • Si se han anidado las vistas de colección, invalidar de adentro hacia afuera. stackoverflow.com/a/34440819/460625

InformationsquelleAutor Mikel Nelson | 2013-01-22

21 Comentarios

  1. 36

    Me estaba poniendo la misma advertencia. Insatisfecho con el «reloadData» enfoque, he encontrado que llamar a [self.collectionView.collectionViewFlowLayout invalidateLayout] antes de establecen el marco de la vista de colección silenciado la advertencia y se obtuvieron los resultados esperados.

    • Lo he probado en ios7 y dice: no se conoce Ningún método de clase para el selector ‘invalidateLayout» ¿qué podría ser la razón?
    • Usted querrá usar [self.collectionView.collectionViewLayout invalidateLayout];
    • no funciona
    • no funciona
    • Respuesta errata corregida para ser [self.collectionView.collectionViewFlowLayout invalidateLayout]
    • +1, Solucionado mi problema. - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; [self.collectionView.collectionViewLayout invalidateLayout]; [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { }]; }

  2. 9

    No lanzar otro de camarón en esta cargado, sin embargo, no aceptado, barbie.

    - (CGSize)collectionView:(UICollectionView *)collectionView 
                      layout:(UICollectionViewLayout *)collectionViewLayout
      sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    
        [collectionView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
        return CGSizeMake(100, collectionView.frame.size.height);
    }

    Establecer el contenido de los insertos, justo antes de devolver el tamaño de la celda hizo el truco para mí.

    Nota:

    Estoy usando un contenedor de vista en un storyboard para cargar la vista de colección dentro de un UIViewController. Traté de configuración que esta en el flowLayout objeto en el guión gráfico. La colección vista en el guión gráfico. Y principal de uno de los UICollectionViewDelegateFlowLayout; aunque no recuerdo cuál. Tampoco estoy seguro de si esto va a funcionar para un diseño vertical.

    • el setContentInset lo hizo por mí, mientras yo regreso a mi costumbre de tamaño completo rect
  3. 6

    En

    [UIViewController willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration]

    Me llamaba, [UICollectionViewLayout invalidateLayout] y parece que funciona bien.

    • invalidateLayout no es un método de UICollectionViewLayout
    • Uso [self.collectionView.collectionViewLayout invalidateLayout];.
    • no wwork para ios 8
    • Como @alguien dijo, en willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration(NSTimeInterval)duration si usamos @Josh método [self.collectionView.collectionViewLayout invalidateLayout]; obras, en iOS 8 la prueba.
  4. 4

    Lo resuelto.

    Usted debe dejar que la altura de flowLayout menos de collcetionView.marco.tamaño.altura.

     [flowLayout setItemSize:CGSizeMake(width, height)];
    
    
     collectionView.frame = CGRectMake(12, 380, 290, 80);
    • Es solucionado gracias.
  5. 4

    Una gran cantidad de soluciones sugerir la adición de invalidateLayout a willAnimateRotationToInterfaceOrientation – pero esto está en desuso desde iOS 8.

    Para iOS 8 y superior, uso:

    - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
    {
        [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    
        [self.collectionView.collectionViewLayout invalidateLayout];
    }

    Gracias a @user7097242 a comentar aquí es un swift4 versión:

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        self.collectionView.collectionViewLayout.invalidateLayout()
    }
    • Esta es una gran respuesta! Aquí está la versión actualizada de Swift 4 versión: ` comisiones de func viewWillTransition(tamaño: CGSize, con coordinador: UIViewControllerTransitionCoordinator) { super.viewWillTransition(a: tamaño, con: coordinador) auto.collectionView.collectionViewLayout.invalidateLayout() }«
    • Gracias! Que no formato bien allí, así que lo he añadido en mi respuesta, espero que bien.
    • Que es perfecto en realidad! No mire para bien como un comentario.
  6. 2

    He encontrado con este mismo problema. Si la vista de colección se muestra en la orientación vertical, las células desaparecen cuando se gira en el paisaje. Hice una combinación de las otras respuestas aquí para solucionarlo.

    Me puse mi punto de vista (el que contiene el UICollectionView) para recibir la UIDeviceOrientationDidChangeNotification notificación. En el método que responde a la notificación, después de la UICollectionView marco se ajustó, hice lo siguiente:

    - (void)orientationChanged:(NSNotification *)notification
    {
        CGSize size = (CGSize){self.frame.size.width - 2*kContentMargin, self.frame.size.height - 2*kContentMargin};
        [self.collectionView.collectionViewLayout setItemSize:size];
    
        [self.collectionView.collectionViewLayout invalidateLayout];
        [self.collectionView reloadData];
    }

    Nota de que el marco de la UICollectionView se establece de forma automática sobre la rotación debido a su resizingMask se establece en este momento de la inicialización:

    self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  7. 2

    Sólo encontró y corrigió el mismo problema. Desde mi solución es más a lo largo de las líneas que estaban pidiendo y no coincide con ninguno de respuesta existente, he publicado aquí.

    #define NUMBER_OF_CELLS_PER_ROW 1
    
    - (UICollectionViewFlowLayout *)flowLayout {
        return (UICollectionViewFlowLayout *)self.collectionViewLayout;
    }
    
    - (CGSize)itemSizeInCurrentOrientation {
        CGFloat windowWidth = self.collectionView.window.bounds.size.width;
    
        CGFloat width = (windowWidth - (self.flowLayout.minimumInteritemSpacing * (NUMBER_OF_CELLS_PER_ROW - 1)) - self.flowLayout.sectionInset.left - self.flowLayout.sectionInset.right)/NUMBER_OF_CELLS_PER_ROW;
    
        CGFloat height = 80.0f;
    
       return CGSizeMake(width, height);
    }
    
    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
        [self.flowLayout invalidateLayout];
        self.flowLayout.itemSize = [self itemSizeInCurrentOrientation];
    }
    
    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
        //Now that the rotation is complete, load the cells.
        [self.collectionView reloadData];
    }
  8. 2

    Esta resuelto para mí:

    -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
        [self.collectionView.collectionViewLayout invalidateLayout];
    }

    Y estoy utilizando este método delegado para establecer el tamaño:

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath

    Y puedo desde allí use esto con el marco correcto después de la rotación:

    self.collectionView.frame.size
  9. 2

    Mi solución fue tan simple como desactivar ‘Ajuste de Desplazamiento de la Vista de Inserciones» para el controlador de vista del IB, ya que necesitaba mi barra de navegación para ser translúcido.

  10. 2

    Este me funciona: (y espero que también funciona para usted!)

    - (void)viewWillLayoutSubviews 
    {     
         self.flowLayout.itemSize = CGSizeMake(self.collectionView.bounds.size.width/4,self.collectionView.bounds.size.height);    
         [self.flowLayout invalidateLayout];
    }
    
    - (void)viewDidLayoutSubviews     
    {
        self.flowLayout.itemSize = CGSizeMake(self.collectionView.bounds.size.width/4,self.collectionView.bounds.size.height); 
    }
    • Esto también trabajó para mí, sin embargo, usted no (necesariamente) la necesidad de actualizar la itemSize en viewWillLayoutSubviews, simplemente lo invalida
  11. 1

    Yo se enfrentó al mismo problema.
    aquí es cómo lo resolví. espero que ayude

    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(    NSTimeInterval)duration
    {
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    
        [self.collectionView reloadData];
    }
  12. 1

    Probar esto…

    UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
    
    layout.itemSize = CGSizeMake(0.1, 0.1);

    Es que funciona para mí.

  13. 0

    Me encontré con el mismo problema al cambiar el tamaño del marco de una UICollectionView. Si he utilizado el método de delegado en FlowLayout para devolver el tamaño de la célula (que se actualizará en función del tamaño de la que contiene UICollectionView), me gustaría obtener el mensaje de error cuando me cambia de tamaño (más pequeño) en el marco de la UICollectionView, pues no se parecen a solicitar al delegado para actualizar la información de tamaño antes de quejarse. Podría, eventualmente, solicitar al delegado método para el tamaño de la información de cuando volver a dibujar, pero aún así sería problema de la advertencia en el momento en que yo le asigna un nuevo método del marco. Para deshacerse de la advertencia, me establezca explícitamente la itemSize propiedad de la UICollectionViewFlowLayout objeto antes de I establecer el marco para un nuevo valor más pequeño. Mi situación es bastante sencilla que creo que puede salirse con la suya haciendo el itemSize de cálculo en este momento (ya que todos mis artículos en la vista de colección son del mismo tamaño), en lugar de según el método de delegado. Sólo la creación de la itemSize de la propiedad, dejando el delegado método implementado hizo no resolver el problema, como creo que se ignora el valor de itemSize si se detecta que el delegado método fue implementado (si es que sabe que está ahí, ¿por qué no lo llaman?!). Espero que esta ayuda – tal vez usted también puede establecer explícitamente el itemSize antes de la rotación.

  14. 0

    Sólo para suprimir la advertencia y (probablemente, no estoy seguro) mejorar el rendimiento que usted puede antes de regresar tamaño en

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath

    comprobar si el controlador está en proceso de rotación y si es devolver algunas de tamaño relativamente pequeño como CGSizeMake(0.1, 0.1)

  15. 0

    Puede subclase UICollectionView y reemplazar setBounds:. No antes de llamar a [super setBounds:] el tamaño de elemento puede ser adaptado a los nuevos límites.

    Usted debe comprobar si el tamaño de los límites ha cambiado, porque setBounds: se invoca también durante el desplazamiento.

  16. 0

    Siguiente código fijo para mí:

    -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return self.collectionView.frame.size;
    }
  17. 0

    He usado un UICollectionViewFlowLayoutInvalidationContext, en la que me calcule el nuevo desplazamiento tal que se mantiene el mismo contenido desplazamiento. Mi propia función collectionViewSizeForOrientation: devuelve el tamaño adecuado. No es perfecto, pero al menos no es de boceto:

    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        CGSize fromCollectionViewSize = [self collectionViewSizeForOrientation:[self interfaceOrientation]];
        CGSize toCollectionViewSize = [self collectionViewSizeForOrientation:toInterfaceOrientation];
    
        CGFloat currentPage = [_collectionView contentOffset].x / [_collectionView bounds].size.width;
        NSInteger itemCount = [_collectionView numberOfItemsInSection:0];
    
        UICollectionViewFlowLayoutInvalidationContext *invalidationContext = [[UICollectionViewFlowLayoutInvalidationContext alloc] init];
    
        [invalidationContext setContentSizeAdjustment:CGSizeMake(toCollectionViewSize.width * itemCount - fromCollectionViewSize.width * itemCount, toCollectionViewSize.height - fromCollectionViewSize.height)];
        [invalidationContext setContentOffsetAdjustment:CGPointMake(currentPage * toCollectionViewSize.width - [_collectionView contentOffset].x, 0)];
    
        [[_collectionView collectionViewLayout] invalidateLayoutWithContext:invalidationContext];
    
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    }

    collectionViewSizeForOrientation: en mi caso es el siguiente, suponiendo que las inserciones y elemento de separación están 0:

    - (CGSize)collectionViewSizeForOrientation:(UIInterfaceOrientation)orientation
    {
        CGSize screenSize = [[UIScreen mainScreen] bounds].size;
    
        CGFloat width = UIInterfaceOrientationIsLandscape(orientation) ? MAX(screenSize.width, screenSize.height) : MIN(screenSize.width, screenSize.height);
        CGFloat height = UIInterfaceOrientationIsLandscape(orientation) ? MIN(screenSize.width, screenSize.height) : MAX(screenSize.width, screenSize.height);
    
        return CGSizeMake(width, height);

    }

  18. 0

    Tratando de encontrar una solución para silenciar estas advertencias en iOS 7 fue resultando difícil para mí. Terminé de recurrir a la creación de subclases mi UICollectionView y se ha añadido el siguiente código.

    - (void)setFrame:(CGRect)frame
    {
        if (!iOS8 && (frame.size.width != self.frame.size.width))
        {
            [self.collectionViewLayout invalidateLayout];
        }
    
        [super setFrame:frame];
    }

    Algunos podrían querer hacer toda una comprobación de tamaño con CGSizeEqualToSize().

  19. 0

    tratar al final de didRotateFromInterfaceOrientation:

    [self.collectionView setNeedsLayout]

    si no funciona, pruebe a mover todo esto de didRotateFromInterfaceOrientation a willRotateToInterfaceOrientation

  20. 0

    Nota: En mi caso, descubrí que éramos configuración de la preferredContentSize propiedad de la UIViewController en cuestión. Si te parece que esto es su caso, usted podría tener que lidiar con el siguiente método de la UICollectionViewDelegateFlowLayout protocolo:

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
        CGSize size = collectionViewLayout.collectionView.bounds.size;
        ...
        return size;
    }
  21. 0

    Sé que esto es una vieja pregunta, pero yo sólo tengo el mismo problema y pasó una hora para resolverlo. Mi problema era que, parece que el UICollectionView del tamaño de trama es siempre malo (lo de la altura no coincide con el contenedor), mientras que yo establezca el tamaño de fotograma de la derecha antes de la UICollectionView diseño de Flujo de delegado se llama. Así que, me puse el UICollectionView tamaño de fotograma de nuevo en el método :

    -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath

    Y que hizo el truco. La altura es de ahora muestran correctamente y la advertencia se ha ido.

Dejar respuesta

Please enter your comment!
Please enter your name here