2013-01-22 13 views
7

Mam UICollectionView z niestandardową podklasą komórek UICollectionViewCell. I w kodzie mam zrobić, co następuje:dequeueReusableCellWithIdentifier nie używając ponownie komórek

[self.collectionView_ registerClass:[AHPinterestCell class] 
     forCellWithReuseIdentifier:@"AHPinterestCell"]; 

jest to, co dzieje się w moim cellForItem

AHPinterestCell *cell = 
       (AHPinterestCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"AHPinterestCell" 
                      forIndexPath:indexPath]; 

jednak wydaje się, że nie jest to ponowne komórkę. W widoku mojej kolekcji na ekranie jest wyświetlanych około 9-10 komórek, jednak gdy wykonuję nieskończone przewijanie, a następnie wywołuję insertItemsAtIndexPath, wywołuje on metodę initWithFrame w mojej komórce niestandardowej, podczas gdy prawdopodobnie powinien ponownie wykorzystać komórki, które już posiadam. Dlaczego to?

EDIT:

dodaję przykładowy projekt demo, który ilustruje problem, link do projektu Xcode można znaleźć here. Zasadniczo robi nieskończony zwój, gdy dojdziesz do dna, po prostu dołącza do niego więcej rzeczy. Ale kiedy to zrobisz, ponownie wywoła metodę init.

+0

@Rob Wołam registerClass w viewDidLoad – adit

+0

@Sang należy po prostu init, jak 10, a następnie reszta kiedy przewijać powinno nigdy wywołuj init ponownie, ponieważ jest ponowne co mam już – adit

+0

@Sang jak upewnić się, że to uruchomi się, gdy stanie się widoczny? Tak więc w moim przypadku mam UICOllectionView, który ma 100 komórek w nim, ale 10 jest wyświetlany na ekranie na raz. Zakładam więc, że tylko 10 init zostanie wywołanych, a reszta zostanie ponownie użyta. – adit

Odpowiedz

4

Krótko mówiąc, Twój kod działa poprawnie. Zgodnie z oczekiwaniami, gdy komórki przewijają ekran, są one oznaczane jako dostępne do ponownego użycia. A jeśli zadzwonisz pod numer dequeueReusableCellWithReuseIdentifier, jeśli jest dostępna komórka do ponownego wykorzystania, zrobi to. Jeśli nie, tworzy jeden.

Czas, w którym zobaczysz wiele tworzonych komórek, to szybkość przewijania lub ciągłego przewijania. Ale jeśli zrobisz krótkie małe zwoje, puść, wstrzymaj, pozwól UI na nadrobienie zaległości i powtórz, wtedy zobaczysz bardzo mało tworzonych komórek.

Rozumiem, że system iOS nadaje priorytet interfejsowi użytkownika i tworzeniu nowych komórek nad usuwaniem starych komórek, umożliwiając ich ponowne użycie. Jeśli więc szybko się przekręcisz, ma problem z nadrabianiem i oznaczaniem starych komórek jako dostępnych do ponownego użycia. Prawdopodobnie nie jest to tak źle, ponieważ prawdopodobnie zapewnia to płynne przepływy kolekcji. Oznaczanie starych komórek do ponownego użycia jest jedną z mniej ważnych rzeczy do zrobienia w iOS. Ale jeśli pamięć jest napięta, może to stanowić problem. Przy okazji, jeśli wstawisz też NSLog w dealloc, zauważysz, że kiedy interfejs użytkownika w końcu zapada w pamięć po wykonaniu naprawdę szybkiego przewijania widoku kolekcji, wyraźnie ma pewną logikę, która mówi "gee, Mam więcej zapasowych komórek, niż naprawdę potrzebuję, zamierzam się ich pozbyć. " W rzeczywistości jest to całkiem sprytna implementacja. Nacisk na szybkość, ale z pewnymi optymalizacjami pamięci, które mają miejsce, gdy interfejs użytkownika uspokoi się.

+0

Rob, świetna obserwacja ... więc jak mogę to zrobić, aby nie tworzył komórek po wstawieniu nowych elementów? Powoduje to problemy z pamięcią, ponieważ przyspiesza. – adit

+0

@adit Podejrzewam, że jeśli używasz 'UICollectionView', utknąłeś z wbudowaną hierarchizacją interfejsu użytkownika nad wykorzystaniem pamięci. Jeśli chcesz, możesz zawsze odrzucić 'UICollectionView' i zamiast tego zaimplementować własną podklasę' UIScrollView' z nieskończonym przewijaniem, która w 'scrollViewDidScroll', nadała priorytet zwolnieniu starych komórek nad utworzeniem nowych komórek. Musisz po prostu dowiedzieć się, ile funkcji 'UICollectionView' chcesz ponownie zastosować w swoim własnym' UIScrollView'. – Rob

0

Zgoda, mam ten sam problem, ale pomyślałem o stworzeniu kategorii, która da mi widoczną komórkę, jeśli jest dostępna.

// Header file UITableView+VisibleCell.h" 
@interface UITableView (VisibleCell) 
- (UITableViewCell*) visibleCellForRowAtIndexPath:(NSIndexPath *)indexPath; 
@end 


// Implementation file UITableView+VisibleCell.m 
#import "UITableView+VisibleCell.h" 

@implementation UITableView (VisibleCell) 

- (UITableViewCell*) visibleCellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    for(UITableViewCell* currentVisibleCell in self.visibleCells) 
    { 
     NSIndexPath* currentPath = [self indexPathForCell: currentVisibleCell ]; 
     if([currentPath isEqual:(id) indexPath]) 
     { 
      return currentVisibleCell; 
     } 
    }  
    return nil; 
}  
@end 

można również uruchomić przez coraz widoczna komórka następnie powrócić cellForRowAtIndexPath zamiast zera, jest to kwestia stylu. (Potrzebowałem tego, aby pobrać UITextField z danym tagiem w danej komórce, aby becomeFIrstResponder, ale cellForRowAtIndexPath przechowywane realokacji moją komórkę, bardzo frustrujące.

+1

Świetnie, działało również dla UICollectionViewCell – zaheer

0

Wyłącz dostęp z ustawieniami urządzenia. Jest to bug. Mam ten sam problem na moim iPadzie mini.

Powiązane problemy