2012-09-24 3 views
6

Wir versuchen, eine UICollectionView mit einem benutzerdefinierten Layout einzurichten. Der Inhalt jeder CollectionViewCell wird ein Bild sein. Insgesamt werden mehrere tausend Bilder und etwa 140-150 zu einer bestimmten Zeit sichtbar sein. Bei einem Aktionsereignis werden möglicherweise alle Zellen in Position und Größe reorganisiert. Das Ziel besteht darin, alle Bewegungsereignisse zu animieren, die derzeit die performBatchUpdates-Methode verwenden. Dies verursacht eine große Verzögerung, bevor alles animiert wird.UICollectionView-Leistungsprobleme bei performBatchUpdates

Bisher haben wir herausgefunden, dass intern die Methode layoutAttributesForItemAtIndexPath für jede einzelne Zelle aufgerufen wird (mehrere tausend insgesamt). Darüber hinaus wird die Methode cellForItemAtIndexPath für mehr Zellen aufgerufen, als tatsächlich auf dem Bildschirm angezeigt werden können.

Gibt es Möglichkeiten, die Leistung der Animation zu verbessern?


Der Standard UICollectionViewFlowLayout kann die Art von Design nicht wirklich bieten wir in der App realisieren möchten. Hier einige unserer Code:

-(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; 
} 

Die layoutAttributesForElementsInRect iteriert über alle Elemente layoutAttributes für allthe Elemente innerhalb des rect Einstellung. Die for-Anweisung bricht auf der ersten Zelle ist über die Grenzen von der unteren rechten Ecke des rect definiert:

-(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; 
} 

Auf Layout-Änderungen die Ergebnisse sind so ziemlich das gleiche, egal, ob die Anzahl der Zellen definiert ist, in der LayoutAttributesForElementsInRect ist begrenzt oder nicht .. Entweder das System erhält die Layout-Attribute für alle Zellen in dort, wenn es nicht begrenzt ist oder es ruft die LayoutAttributesForElementAtIndexPath-Methode für alle fehlenden Zellen, wenn es begrenzt ist. Insgesamt werden die Attribute für jede einzelne Zelle irgendwie verwendet.

-(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

Bitte senden Sie Ihren Code von Ihrem UICollectionViewLayout. –

Antwort

3

Ohne Code zu sehen, meine Vermutung ist, dass Ihr layoutAttributesForElementsInRect Verfahren durch alle Elemente in Ihrer Sammlung iteriert, und das ist wiederum, was die anderen Methoden verursacht über genannt werden. layoutAttributesForElementsInRect gibt Ihnen einen Hinweis - das heißt, das CGRect, das an Sie übergeben wird -, für welche Elemente Sie layoutAttributesForItemAtIndexPath aufrufen müssen, in Bezug auf das, was auf dem Bildschirm angezeigt wird.

Dies könnte Teil des Leistungsproblems sein - das heißt, das benutzerdefinierte Layout so anzupassen, dass es schlau ist, welche Elemente es aktualisiert.

Die anderen Probleme betreffen die Animationsleistung im Allgemeinen. Eine Sache, auf die Sie achten sollten, ist, ob eine Art Compositing stattfindet - stellen Sie sicher, dass Ihre Bilder undurchsichtig sind. Eine andere Sache ist, wenn Sie Schatten auf Ihrem Bild verwenden, können diese teuer zu animieren sein. Eine Möglichkeit, die Animationsleistung von Schatten zu verbessern, ist der shadowPath-Wert, wenn das Bild in der Größe geändert wird. Wenn Sie Schatten haben, lassen Sie es mich wissen und posten Sie dafür einen Code.

+0

Wir haben bereits alle Elemente innerhalb des rect, die dem LayoutAttributesForElementsInRect übergeben werden, iteriert. Immer noch ruft das System die layoutAttributesForItemAtIndexPath-Methode für alle Zellen außerhalb des Rect auf.Im Falle von Bildern verwenden wir überhaupt keine Schatten und sind bereits undurchsichtig. Ein Problem könnte darin bestehen, dass die Anzahl der Ansichten gleichzeitig sichtbar ist (etwa 140). –

+0

Es wäre hilfreich, wenn Sie Code gepostet haben. Ein Vorschlag zum Debuggen implementiert dieselbe Auflistungsansicht mit dem integrierten UICollectionViewFlowLayout und gibt ihm ähnliche Parameter wie in Ihrer benutzerdefinierten Ansicht. Löse Ereignisse aus, die das UICollectionViewFlowLayout in bedeutender Weise reorganisieren, und sieh nach, ob die Animationen besser sind. –

+0

FYI, Apple hat endlich ein Beispielcode-Projekt für CollectionViews veröffentlicht. Leider ist es eine lächerlich einfache Implementierung - kein benutzerdefiniertes Layout, das ist der Code, den ich wirklich sehen muss. –

0

Dies scheint verursacht zu werden, indem versucht wird, Zellen zu Abschnitten hinzuzufügen, die Header-Ansichten aber keine Zellen bereits in ihnen haben.

Die Fehlermeldung ist monumental nicht hilfreich, und es dauerte mehrere Stunden Aufwand, um es aufzuspüren.