ios - tutorial - Advertencia: UICollectionViewFlowLayout tiene una falta de coincidencia de cuadros en caché para la ruta del índice ''abc''
uicollectionviewcell swift (7)
Esto probablemente ocurra porque el diseño de flujo "xyz" está modificando los atributos devueltos por UICollectionViewFlowLayout sin copiarlos
Y por supuesto, eso es lo que estás haciendo:
private override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = super.layoutAttributesForItemAtIndexPath(indexPath)
let distance = CGRectGetMidX(attributes!.frame) - self.midX;
var transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, -distance, 0, -self.width);
attributes!.transform3D = CATransform3DIdentity;
return attributes
}
Espero que si simplemente dices:
let attributes =
super.layoutAttributesForItemAtIndexPath(indexPath).copy()
as! UICollectionViewLayoutAttributes
o similar, el problema desaparecerá.
Este es el código que causa la advertencia:
private override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = super.layoutAttributesForItemAtIndexPath(indexPath)
let distance = CGRectGetMidX(attributes!.frame) - self.midX;
var transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, -distance, 0, -self.width);
attributes!.transform3D = CATransform3DIdentity;
return attributes
}
La consola también imprime:
Es probable que esto ocurra porque el diseño de flujo "xyz" modifica los atributos devueltos por UICollectionViewFlowLayout sin copiarlos.
¿Cómo soluciono esta advertencia?
Además de la gran respuesta anterior.
Sé que el código de ejemplo está escrito en swift, pero pensé que podría ser útil tener la versión Objective-C.
Para Objective-C, esto no funcionará, porque la función de copia solo hace una copia superficial. Tendrás que hacer esto:
NSArray * original = [super layoutAttributesForElementsInRect:rect];
NSArray * attributes = [[NSArray alloc] initWithArray:original copyItems:YES];
He añadido una variable temporal para la legibilidad.
Agregando a la respuesta de @Georgi
<NSCopying>
debe estar conformado y agregar una copia del mensaje de copia a layoutAttributesForItemAtIndexPath
UICollectionViewLayoutAttributes* attributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
He subclasificado UICollectionViewFlowLayout
. Dentro de layoutAttributesForElementsInRect()
hice este cambio:
cambiar de
guard let attributesForItem: UICollectionViewLayoutAttributes = self.layoutAttributesForItemAtIndexPath(indexPath) else {
return
}
cambiar a
guard let attributesForItem = self.layoutAttributesForItemAtIndexPath(indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
return
}
No es la respuesta a la pregunta original, pero puede ayudar para layoutAttributesForElements (en rect: CGRect) (Swift 3.0):
let safeAttributes = super.layoutAttributesForElements(in: rect)?.map { $0.copy() as! UICollectionViewLayoutAttributes }
safeAttributes?.forEach { /* do something with attributes*/ }
Respuesta actualizada para Swift 3!
para func layoutAttributesForElements
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else {
return nil
}
guard let attributesToReturn = attributes.map( { $0.copy() }) as? [UICollectionViewLayoutAttributes] else {
return nil
}
return attributesToReturn
}
para func layoutAttributesForItem
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
guard let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
return nil
}
return currentItemAttributes
}
Si anula ambas funciones, debe llamar a copiar en ambas funciones.
Buena codificación!
Tuve este problema al anular layoutAttributesForElementsInRect
. Iterar a través de cada elemento en la super.layoutAttributesForElementsInRect(rect)
y llamar a la copia no me funcionaba, así que terminé recurriendo a las clases de Foundation y usando los elementos de copyItems
NSArray
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// unwrap super''s attributes
guard let superArray = super.layoutAttributesForElementsInRect(rect) else { return nil }
// copy items
guard let attributes = NSArray(array: superArray, copyItems: true) as? [UICollectionViewLayoutAttributes] else { return nil }
// modify attributes
return attributes
}