es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La vista de colección de tamaño automático entra en un bucle recursivo en iOS 15.

Tengo una vista de colección de tamaño automático y cuando llamo a super.layoutSubviews mi aplicación se bloquea ya que la vista de colección entra en un bucle de actualización recursivo. Esto funcionaba bien en iOS 14 y anteriores. Pero lo observé en iOS 15 en adelante.

class DynamicCollectionView: UICollectionView {

    override var contentSize: CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        if bounds.size != intrinsicContentSize {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        return contentSize
    }

    override func reloadData() {
        super.reloadData()
        invalidateIntrinsicContentSize()
        layoutIfNeeded()
    }
}

El error dice:

Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘UICollectionView (<kpflagship.selfsizingcollectionview 0x7f896b260e00=””>) se encuentra atrapado en su bucle de actualización/diseño. Esto puede ocurrir por muchas razones, incluyendo vistas de tamaño automático cuyos atributos preferidos no devuelven un tamaño consistente. Para solucionar este problema, revisa la aplicación Console en la categoría “UICollectionViewRecursion” para obtener registros.'</kpflagship.selfsizingcollectionview>

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Solución para el problema de bloqueo en iOS 15 en adelante

    Este problema de bloqueo se debe a que las vistas de tamaño automático devuelven atributos preferidos inconsistentes. Para resolver este problema, puedes probar las siguientes soluciones:

    1. Utilizar UIViewPropertyAnimator para actualizar el diseño:
    override func layoutSubviews() {
        super.layoutSubviews()
        UIViewPropertyAnimator.running(in: self, withDuration: 0) {
            if bounds.size != intrinsicContentSize {
                invalidateIntrinsicContentSize()
                self.superview?.layoutIfNeeded() // añade esta línea para actualizar el diseño del contenedor
            }
        }
    }
    
    1. Desactivar la estimación del tamaño del elemento:
    if #available(iOS 15.0, *) {
        collectionViewLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    }
    
    1. Eliminar override var intrinsicContentSize: CGSize e implementar un diseño de tamaño automático:
    class DynamicCollectionView: UICollectionViewFlowLayout {
    
        override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext {
            let context = super.invalidationContext(forBoundsChange: newBounds) as! UICollectionViewFlowLayoutInvalidationContext
            context.invalidateFlowLayoutDelegateMetrics = newBounds.size != collectionView?.bounds.size
            return context
        }
    
        override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
            return true
        }
    }
    

    Estas soluciones pueden ayudarte a resolver el problema de bloqueo en iOS 15 en adelante. Puedes probarlas y elegir la que funcione mejor para tu proyecto.

Comments are closed.