2012-09-24 57 views
6

Estamos tratando de configurar un UICollectionView con un diseño personalizado. El contenido de cada CollectionViewCell será una imagen. Sobre todo habrá varios miles de imágenes y aproximadamente 140-150 siendo visibles en un momento determinado. En un evento de acción, potencialmente todas las celdas se reorganizarán en posición y tamaño. El objetivo es animar todos los eventos en movimiento que actualmente usan el método performBatchUpdates. Esto provoca un gran retraso antes de que todo se anima.UICollectionView Problemas de rendimiento en performBatchUpdates

Hasta aquí hemos descubierto que internamente se llama al método layoutAttributesForItemAtIndexPath para cada celda (varios miles en total). Además, se llama al método cellForItemAtIndexPath para obtener más celdas de las que realmente se pueden mostrar en la pantalla.

¿Hay alguna posibilidad de mejorar el rendimiento de la animación?


El valor predeterminado UICollectionViewFlowLayout en realidad no puede ofrecer el tipo de diseño que queremos realizar en la aplicación. He aquí algunos de nuestro código:

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
RPDataModel *dm = [RPDataModel sharedInstance]; //Singleton holding some global information 
NSArray *plistArray = dm.plistArray; //Array containing the contents of the cells 
NSDictionary *dic = plistArray[[indexPath item]]; 
RPCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath]; 
cell.label.text = [NSString stringWithFormat:@"%@",dic[@"name"]]; 
cell.layer.borderColor = nil; 
cell.layer.borderWidth = 0.0f; 
[cell loadAndSetImageInBackgroundWithLocalFilePath:dic[@"path"]]; //custom method realizing asynchronous loading of the image inside of each cell 
return cell; 
} 

Los itera layoutAttributesForElementsInRect más de todos los elementos de ajuste para layoutAttributes allthe elementos dentro del rect. Las pausas para-declaración sobre la primera celda que se está más allá de las fronteras definidas por la esquina inferior derecha de la rect:

-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { 
NSMutableArray* attributes = [NSMutableArray array]; 
RPDataModel *dm = [RPDataModel sharedInstance]; 
for (int i = 0; i < dm.cellCount; i++) { 
    CGRect cellRect = [self.rp getCell:i]; //self.rp = custom object offering methods to get information about cells; the getCell method returns the rect of a single cell 
    if (CGRectIntersectsRect(rect, cellRect)) { 
     NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[dm.relevanceArray[i][@"product"] intValue] inSection:0]; 
     UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 
     attribute.size = cellRect.size; 
     attribute.center = CGPointMake(cellRect.origin.x + attribute.size.width/2, cellRect.origin.y + attribute.size.height/2); 
     [attributes addObject:attribute]; 
    } else if (cellRect.origin.x > rect.origin.x + rect.size.width && cellRect.origin.y > rect.origin.y + rect.size.height) { 
     break; 
    } 
} 
return attributes; 
} 

El diseño cambia los resultados son más o menos los mismos sin importar si se está definiendo el número de células en layoutAttributesForElementsInRect está limitado o no ... O el sistema obtiene los atributos de diseño para todas las celdas allí si no está limitado o llama al método layoutAttributesForElementAtIndexPath para todas las celdas que faltan si está limitado. En general, los atributos para cada celda se utilizan de alguna manera.

-(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { 
RPDataModel *dm = [RPDataModel sharedInstance]; 
UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 
CGRect cellRect = [self.rp getCell:[dm.indexDictionary[@(indexPath.item)] intValue]]; 
attribute.size = cellRect.size; 
attribute.center = CGPointMake(cellRect.origin.x + attribute.size.width/2, cellRect.origin.y + attribute.size.height/2); 
return attribute; 
}  
+0

Publica el código de tu UICollectionViewLayout. –

Respuesta

3

Sin ver el código, mi conjetura es que su método se layoutAttributesForElementsInRect iteración a través de todos los artículos en su colección, y que es, a su vez, lo que está causando los otros métodos para conseguir llaman excesivamente. layoutAttributesForElementsInRect le proporciona una pista, es decir, el CGRect que le está transmitiendo, sobre los elementos a los que debe llamar layoutAttributesForItemAtIndexPath, en términos de lo que está en la pantalla.

De modo que eso puede ser parte del problema de rendimiento, es decir, ajustar su diseño personalizado para que sea inteligente sobre qué elementos se está actualizando.

Los otros problemas se refieren al rendimiento de la animación en general. Una cosa a tener en cuenta es si hay algún tipo de composición en curso: asegúrese de que sus imágenes sean opacas. Otra cosa es que si usa sombras en su imagen, puede ser costoso para animar. Una forma de mejorar el rendimiento de la animación de las sombras es configurar el valor de shadowPath cuando se cambie el tamaño de la imagen; si tiene sombras, hágamelo saber y publique un código para hacerlo.

+0

Ya solo iteramos sobre todos los elementos que están dentro del rect dados a layoutAttributesForElementsInRect. Aún así, el sistema llama al método layoutAttributesForItemAtIndexPath para todas las celdas fuera de rect.En el caso de las imágenes, no usamos ninguna sombra y ya son opacas. Un problema podría ser la cantidad de vistas visibles a la vez (alrededor de 140). –

+0

Sería útil si publicó el código. Una sugerencia, para fines de depuración, implementar la misma vista de colección utilizando el UICollectionViewFlowLayout incorporado, y darle parámetros similares a los que está usando en su vista personalizada. Desencadenar eventos que causan que UICollectionViewFlowLayout se reorganice de manera significativa y ver si las animaciones son mejores. –

+0

FYI, Apple finalmente publicó un proyecto de código de muestra para CollectionViews. Desafortunadamente, es una implementación sumamente ridículamente simple, sin diseño personalizado, que es el código que realmente necesito ver. –

0

Parece que esto se debe a que intenta agregar celdas a secciones que tienen vistas de encabezado pero no hay celdas en ellas.

El mensaje de error es monumentalmente inútil, y se necesitaron varias horas de esfuerzo para rastrearlo.

Cuestiones relacionadas