2016-03-22 5 views
0

Ich habe rund 14 Artikel in meiner SammlungView und das Scrollen ist überhaupt nicht glatt. Ich verwende automatisches Layout (meine Einschränkungen protokollieren keine Fehler) und ich verwende die Eigenschaft cornerRadius (es ist eine Messaging-App).UICollectionView Scroll-Leistung Horrible

Ich habe versucht zu analysieren es die Zeit Profiler Instrument, und das war, was ich sehe, wenn ich blättern:

enter image description here

Leider „in Xcode Reveal“ ausgegraut ist, so kann ich nicht Sehen Sie genau, welche Zeile für immer dauert. Ich berechne jedoch die Größe jedes Artikels. Ich frage mich, was die riesige 9377 ms Verzögerung sein könnte? Ich verwende keine geordneten Sets, wenn ich mich richtig erinnere.

Hier ist meine cellForItemAtIndexpath Methode:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 

    //Define Message 
    Message *message = (Message *)[self.messages objectAtIndex:indexPath.item]; 

    //Check Message Type 
    switch (message.type) { 
     case MessageTypeText: { 

      //Initialize Cell 
      TextMessageItem *cell = (TextMessageItem *)[collectionView dequeueReusableCellWithReuseIdentifier:kTextMessageItemIdentifier forIndexPath:indexPath]; 

      //Return Cell 
      return cell; 

      break; 
     } 
    } 

    return nil; 
} 

Hier ist, wie ich die Höhe bin Berechnung:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 

    //Retrieve the right message 
    Message *message = (Message *)[self.messages objectAtIndex:indexPath.row]; 

    //Check Message Type 
    switch (message.type) { 
     case MessageTypeText: { 

      //Create a temporary cell to get the correct size 
      TextMessageItem *tempCell = [[TextMessageItem alloc] init]; 

      //Configure the cell 
      [self collectionView:collectionView configureTextCell:tempCell atIndexPath:indexPath]; 

      CGSize s = [tempCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize withHorizontalFittingPriority:UILayoutPriorityDefaultHigh verticalFittingPriority:UILayoutPriorityDefaultLow]; 

      //Return Content Size 
      return CGSizeMake(self.collectionView.bounds.size.width, s.height); 

      break; 
     } 
    } 

    //Return 
    return CGSizeMake(0, 0); 
} 

Meine WillDisplayCell Methode:

- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { 

    //Retrieve message from our array of messages 
    Message *message = (Message *)[self.messages objectAtIndex:indexPath.row]; 

    //Check Message Type 
    switch (message.type) { 
     case MessageTypeText: { 

      //Cast Cell 
      TextMessageItem *textItem = (TextMessageItem *)cell; 
      [self collectionView:collectionView configureTextCell:textItem atIndexPath:indexPath]; 

      break; 
     } 
    } 
} 

Und schließlich, das ist meine Gewohnheit configureTextCell Methode:

- (void)collectionView:(UICollectionView *)collectionView configureTextCell:(TextMessageItem *)item atIndexPath:(NSIndexPath *)indexPath { 

    //Retrieve Message 
    Message *message = (Message *)[self.messages objectAtIndex:indexPath.item]; 

    //Display Timestamp if Needed 
    [self displayTimestampForItemIfNeeded:item atIndex:indexPath.item]; 

    //Update Top Message Padding Based On Who Sent The Previous Message 
    [self updateDistanceFromPreviousMessageForItem:item atIndex:indexPath.item]; 

    //Display Delivery Status if Needed (e.g. Delivered) 
    [self displayDeliveryStatusForItemIfNeeded:item atIndex:indexPath.item]; 

    //Set Message 
    [item setMessage:message]; 
} 
+0

Könnte es sein, dass mein 'cellForItemAtIndexpath' nicht korrekt implementiert ist? Meine 'UICollectionViewCell'-Unterklasse wird programmgesteuert ausgeführt (keine Storyboard- oder XIB-Dateien), und ich stelle fest, dass beim ersten Laden die' initWithFrame'-Methode für jedes Element in meinem self.messages-Array aufgerufen wird. Ist das normal? – KingPolygon

Antwort

0

Die Verwendung von Eckenradien oder Ebenenmasken ist eine gute Möglichkeit, die Scrollleistung zu verringern, da das Compositing viel teurer ist. Stattdessen können Sie einen CAShapeLayer mit abgerundeten Ecken verwenden, um Ihre Ansicht zu sichern oder als Teil Ihrer Ansicht. Oder Sie können Ihren Inhalt mit abgerundeten Ecken in ein Bild zeichnen, das Sie zu Ihrer Ansicht hinzufügen. Sie sollten auch vermeiden, dass Ihre Ansicht "Clip-to-Bounds" aufweist. (Ich tippe dieses auf meinem Handy weg von meinem Computer, so dass ich jetzt keine Schnipsel einfügen kann.)

+0

Danke Mustang. Lassen Sie mich versuchen, ein paar Änderungen vorzunehmen, die Sie vorschlagen, und sehen Sie, ob es einen spürbaren Unterschied gibt. – KingPolygon

+0

Ich habe versucht, was Sie vorschlagen, und obwohl es ein wenig hilft, ist es immer noch deutlich verzögert. Die Zeitprofileroperation fiel von 9377 ms auf 8800 ms. Die eigentliche Frage ist also ... was könnte 8800ms kosten? Dies wird nur beim Scrollen angezeigt, nicht bei viewDidLoad, wenn das hilft, es einzugrenzen. – KingPolygon

+0

Wenn ich eine Sekunde bekomme, werde ich mir Ihren Code genauer ansehen. Eine andere Sache, die Sie nie tun möchten, ist die Änderung der Bedingungen bei prepareForReuse time oder dequeueReusableCellWithReuseIdentifier time. Stellen Sie diese zur Init-Zeit ein. – Mustang