2013-07-17 26 views
14

Ho un UICollectionView con una griglia di immagini. Quando si tocca su uno, si apre la griglia e mostra una sottoview con alcuni dettagli. Come questo:UICollectionView non rimuove le vecchie celle dopo lo scorrimento

Supposed to look like this

apro la griglia nel mio UICollectionViewLayout regolando le UICollectionViewLayoutAttributes e impostando una traduzione sulla proprietà Transform3D per tutte le celle di sotto della riga corrente della voce selezionata. Funziona molto bene, ed è un'animazione molto migliore e un approccio più semplice rispetto al mio primo tentativo di inserire un'altra cella nella griglia che è di dimensioni diverse dalle altre.

In ogni caso ... funziona la maggior parte del tempo, ma poi, dopo un uso continuato, vedo le vecchie immagini sulla vista di raccolta. Sono come le cellule fantasma. Non riesco a fare clic su di essi, è come se non fossero stati rimossi correttamente dalla vista raccolta e si siedono in cima alle celle, impedendo i rubinetti e solo per essere un fastidio. Come questo:

Problem looks like this

Tutte le idee perché queste cellule stanno facendo questo?

MODIFICA: Mi piacerebbe aggiungere, penso che accada solo quando faccio scorrere velocemente la vista raccolta. Ho scritto la mia sostituzione UICollectionViewFlowLayout per verificare se si verifica ancora. Lo fa.

MODIFICA 2: Le trasformazioni o il layout 3D non hanno nulla a che fare con questo. Deve essere un bug in UICollectionView. Posso sfruttare lo scrolling molto veloce, lasciando che si fermi e poi interrogando le visualizzazioni sullo schermo. Ci sono spesso il doppio del numero di celle, ma sono nascoste in quanto sono impilate l'una sull'altra. La mia implementazione sopra li rivela a causa della traduzione che faccio.

Questo può davvero danneggiare le prestazioni.

Vedere la mia risposta per una soluzione.

+0

Potrebbe inviare uno screenshot? –

+0

Un momento casuale bizzarro, visto un paio d'ore fa. Guardato la pagina del tuo profilo. Ho avuto un'idea per un'app. Sono andato alla ricerca dell'API di Flickr. Ho visto FlickrKit su Github. Riconosciuto il nome. LOL! Netception! – Fogmeister

+0

sì, mi aggiro ..... e tu sei a Leeds, e io vengo da Leeds ... in realtà, sto per guidare lì. – bandejapaisa

risposta

14

La seconda modifica dei dettagli della mia domanda spiega perché questo si sta verificando ed ecco la mia soluzione alternativa. Non è a prova di proiettile, ma funziona nel mio caso, e se si verificano somethign simile si potrebbe modificare la mia soluzione:

- (void) removeNaughtyLingeringCells { 

    // 1. Find the visible cells 
    NSArray *visibleCells = self.collectionView.visibleCells; 
    //NSLog(@"We have %i visible cells", visibleCells.count); 

    // 2. Find the visible rect of the collection view on screen now 
    CGRect visibleRect; 
    visibleRect.origin = self.collectionView.contentOffset; 
    visibleRect.size = self.collectionView.bounds.size; 
    //NSLog(@"Rect %@", NSStringFromCGRect(visibleRect)); 


    // 3. Find the subviews that shouldn't be there and remove them 
    //NSLog(@"We have %i subviews", self.collectionView.subviews.count); 
    for (UIView *aView in [self.collectionView subviews]) { 
     if ([aView isKindOfClass:UICollectionViewCell.class]) { 
      CGPoint origin = aView.frame.origin; 
      if(CGRectContainsPoint(visibleRect, origin)) { 
       if (![visibleCells containsObject:aView]) { 
        [aView removeFromSuperview]; 
       } 
      } 
     } 
    } 
    //NSLog(@"%i views shouldn't be there", viewsShouldntBeThere.count); 

    // 4. Refresh the collection view display 
    [self.collectionView setNeedsDisplay];  
} 

e

- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 
    if (!decelerate) { 
     [self removeNaughtyLingeringCells]; 
    } 
} 

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 
    [self removeNaughtyLingeringCells]; 
} 
+1

Grazie mille! Nel mio caso, la rimozione delle celle 'Nascoste' nella stessa situazione funziona perfettamente. Inoltre, il mio modo di riprodurre questo problema è: 1. Scorri molto velocemente. 2. Attendere che la decelerazione si arresti. 3. Elimina una cella. 4. Attendi che l'animazione di cancellazione finisca. –

2

Un rapido ulteriore commento a bandejapaisa di: sotto iOS 6 solo , Ho trovato che UICollectionView aveva anche l'abitudine di pasticciare le transizioni animate. Le celle originali rimarrebbero dov'erano, le copie sarebbero state fatte e quindi le copie sarebbero state animate. Di solito in cima agli originali ma non sempre. Quindi un semplice test sui limiti non era sufficiente.

ho pertanto scritto una sottoclasse personalizzata di UICollectionView che fa la seguente:

- (void)didAddSubview:(UIView *)subview 
{ 
    [super didAddSubview:subview]; 

    // 
    // iOS 6 contains a bug whereby it fails to remove subviews, ever as far as I can make out. 
    // This is a workaround for that. So, if this is iOS 6... 
    // 
    if(![UIViewController instancesRespondToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) 
    { 
     // ... then we'll want to wait until visibleCells has definitely been updated ... 
     dispatch_async(dispatch_get_main_queue(), 
     ^{ 
      // ... then we'll manually remove anything that's a sub of UICollectionViewCell 
      // and isn't currently listed as a visible cell 
      NSArray *visibleCells = self.visibleCells; 
      for(UIView *view in self.subviews) 
      { 
       if([view isKindOfClass:[UICollectionViewCell class]] && ![visibleCells containsObject:view]) 
        [view removeFromSuperview]; 
      } 
     }); 
    } 
} 

Ovviamente è un peccato che '' questa iOS 6' test non può essere un po' più diretto, ma è nascosta via in un categoria nel mio codice attuale.

+0

Ho visto questo strano effetto "fantasma" durante lo scorrimento veloce chiamando PerformBatchUpdate: animazioni e non avevo * no * idea di cosa fosse. Non mi sarebbe mai venuto in mente che la vista della collezione stia creando una nuova cella per una cella attualmente sullo schermo - sembra controproducente. Buona cattura, grazie – SG1

0

versione estensione Uno Swift UICollectionView della risposta di bandejapaisa:

extension UICollectionView { 

    func removeNaughtyLingeringCells() { 

     // 1. Find the visible cells 
     let visibleCells = self.visibleCells() 
     //NSLog("We have %i visible cells", visibleCells.count) 


     // 2. Find the visible rect of the collection view on screen now 
     let visibleRect = CGRectOffset(bounds, contentOffset.x, contentOffset.y) 
     //NSLog("Rect %@", NSStringFromCGRect(visibleRect)) 


     // 3. Find the subviews that shouldn't be there and remove them 
     //NSLog("We have %i subviews", subviews.count) 
     for aView in subviews { 
      if let aCollectionViewCell = aView as? UICollectionViewCell { 

       let origin = aView.frame.origin 
       if (CGRectContainsPoint(visibleRect, origin)) { 
        if (!visibleCells.contains(aCollectionViewCell)) { 
         aView.removeFromSuperview() 
        } 
       } 

      } 
     } 

     // 4. Refresh the collection view display 
     setNeedsDisplay() 
    } 
} 
Problemi correlati