Si sta tentando di configurare UICollectionView con un layout personalizzato. Il contenuto di ciascuna CollectionViewCell sarà un'immagine. Oltre a tutto ci saranno diverse migliaia di immagini e circa 140-150 sarà visibile in una certa ora. In un evento di azione potenzialmente tutte le celle saranno riorganizzate in posizione e dimensioni. L'obiettivo è animare tutti gli eventi in movimento attualmente utilizzando il metodo performBatchUpdates. Ciò causa un enorme ritardo prima che tutto si animi.UICollectionView Problemi relativi alle prestazioni su performBatchUpdates
Finora abbiamo scoperto che internamente il metodo layoutAttributesForItemAtIndexPath viene chiamato per ogni singola cella (diverse migliaia in totale). Inoltre, il metodo cellForItemAtIndexPath viene chiamato per più celle di quelle che possono effettivamente essere visualizzate sullo schermo.
Esistono possibilità per migliorare le prestazioni dell'animazione?
L'impostazione predefinita UICollectionViewFlowLayout non può realmente offrire il tipo di design che vogliamo realizzare in app. Ecco alcuni dei nostro codice:
-(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;
}
I itera layoutAttributesForElementsInRect su tutti gli elementi di impostazione layoutAttributes per tuttiIl elementi all'interno del rettangolo. Le interruzioni per-dichiarazione sulla prima cella essendo oltre i confini definiti dal nell'angolo in basso a destra del rettangolo:
-(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;
}
Il layout cambia i risultati sono praticamente la stessa, non importa se in fase di definizione il numero di cellule nel layoutAttributesForElementsInRect è limitato o no. O il sistema ottiene gli attributi di layout per tutte le celle in là se non è limitato o chiama il metodo layoutAttributesForElementAtIndexPath per tutte le celle mancanti se è limitato. Nel complesso, gli attributi per ogni singola cella vengono utilizzati in qualche modo.
-(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;
}
Inserisci il tuo codice dal tuo UICollectionViewLayout. –