2011-02-11 23 views
7

Mam UITableView z listą elementów, z których każda ma swój własny obraz. Pomyślałem, że przykładowy projekt LazyTableImages firmy Apple byłby idealny do nauki i używał do implementacji tego samego rodzaju procesu asynchronicznego pobierania obrazów, po pobraniu oryginalnych danych listowych.Pytanie o próbkę Apple LazyTableImages - Nie zachowuje się dokładnie tak jak sklep z aplikacjami

W większości przypadków działa całkiem nieźle, z wyjątkiem zauważyłem subtelną różnicę w zachowaniu między tą przykładową aplikacją a faktycznym pobieraniem obrazów przez sklep z aplikacjami.

Jeśli uruchomisz próbkę LazyTableImages, zrób szybkie szybkie przewijanie w dół, zobaczysz, że obrazy nie są wyświetlane aż do momentu, gdy przewijanie całkowicie się zatrzyma.

Teraz, jeśli wykonasz ten sam test z listą produktów w rzeczywistym sklepie z aplikacjami, zobaczysz, że obrazy zaczynają się wyświetlać, gdy tylko pojawią się nowe elementy, nawet jeśli przewijanie jeszcze się nie zatrzymało .

Próbuję osiągnąć te same wyniki, ale jak na razie nie robię żadnych postępów. Czy ktoś ma jakieś pomysły, jak to zrobić?

Dzięki!

Odpowiedz

10

jestem zbity z tropu, że nikt nie mógł na to odpowiedzieć ...

Więc w końcu zorientowali się, jak acheive się dokładnie sam efekt, który jest używany w rzeczywistym sklepie z aplikacjami, w odniesieniu do tego, jak ikony są pobierane/wyświetlane.

Weź przykładowy projekt LazyTableImages i wykonaj kilka uproszczonych modyfikacji.

  1. Idź do kontrolera widoku głównego i usunąć wszystkie kontrole dotyczące przewijanie jest stół i/lub zwalniania w cellForRowAtIndexPath

  2. Usuń wszystkie połączenia loadImagesForOnScreenRows, a tym samym usunąć tę metodę, jak również.

  3. Idź do IconDownload.m i zmienić metodę startDownload do nie zrobić asynchronicznej obrazu Downlaod, ale zamiast zrobić synchronizacji pobrania na wątek w tle.Usuń cały kod w startDownload, i dodaj następujący, więc wygląda to tak:

 

- (void)startDownload 
{ 
    NSOperationQueue *queue = [NSOperationQueue new]; 
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImage) object:nil]; 

    [queue addOperation:operation]; 

    [operation release]; 
    [queue release]; 
} 
 

Następnie dodać LoadImage, tak:

 

- (void)loadImage 
{ 
    NSData *imageData = [[NSData alloc] initWithContents OfURL:[NSURL URLWithString:appRecord.imageURLString]]; 
    self.apprecord.appIcon = [UIImage imageWithData:imageData]; 
    [imageData release]; 

    [self performSelectorOnMainThread:@selector(notifyMainThread) withObject:nil waitUntilDone:NO]; 
} 
 

Następnie dodać notifyMainThread tak :

 

- (void)notifyMainThread 
{ 
    [delegate appImageDidLoad:self.indexPathInTableView]; 
} 
 

Zrobione! Uruchom go, a zobaczysz dokładne zachowanie sklepu z aplikacjami, nie musisz już czekać na pobieranie obrazów, dopóki nie skończy się przewijanie i nie będziesz czekać na wyświetlanie obrazów do momentu zatrzymania przewijania lub do momentu, gdy użytkownik usunie palec z ekranu.

Obrazy są pobierane, gdy tylko komórka jest gotowa do wyświetlenia, a obraz jest wyświetlany natychmiast po pobraniu, kropka.

Przepraszam za ewentualne literówki, nie wklej ten z mojego app, wpisałem go, ponieważ jestem z dala od mojego mac teraz ...

W każdym razie, mam nadzieję, że to pomoże wam wszystkim. ..

+0

Genialny! Dzięki za zamieszczenie tego! –

+0

Doceniam twój wkład w poprawę przykładu Apple. Twoje rozwiązanie działa częściowo. Delegaci przewijania powinni ** NIE ** zostać usunięci, lub kontroler widoku nie wie, kiedy rozpocząć pobieranie ikon. 'LoadImagesForOnScreenRows' powinno być również wywołane w' viewDidLoad' lub 'viewDidAppear', w zależności od użycia. – Raptor

+0

Przyjemnie, ale zmienia cały kod przykładowy. Nie używa już NSURLConnection. – yosh

0

Zapoznaj się z UIScrollViewDelegate. Zaimplementowałem coś takiego, słuchając dla scrollViewDidScroll:, obliczając prędkość przewijania (sprawdzając wartość contentOffset względem ostatnio zarejestrowanego contentOffset, podzieloną przez różnicę czasu) i rozpoczynając ładowanie obrazów, gdy prędkość spadnie poniżej pewnego progu. (Można osiągnąć coś podobnego również za pomocą UIScrollViewDelegate's scrollViewDidEndDragging:willDecelerate:).

Oczywiście nie trzeba sprawdzać prędkości; możesz po prostu załadować obrazy na UITableViewDelegate 's tableView:willDisplayCell:forRowAtIndexPath: za każdym razem, gdy zobaczysz nową komórkę, ale odkryłem, że jeśli użytkownik przegląda mnóstwo komórek, nie musisz się martwić, dopóki nie zobaczysz, że spowalniają w dół, aby przeglądać.

+0

Próbowałem tego. Sprawdziłem, czy wywołania, aby pobrać nowo wyświetlone zdjęcia przedmiotów, są wykonywane natychmiast. Jednak connectionDidFinishLoading: nigdy nie zostanie wywołany, dopóki przewijanie nie zakończy się całkowicie. Naprawdę jestem zdezorientowany tym zachowaniem ... – bpatrick100

+0

Innym sposobem opisania przykładowego zachowania aplikacji jest przesunięcie palcem po liście, ale nie zwolnij palca (trzymaj go na ekranie), zobaczysz, że obrazy nie wyświetlają się. Następnie, gdy tylko puścisz palec, obrazy zostaną wyświetlone. Wygląda na to, że jest to zachowanie jednowątkowe. Zastanawiam się, czy to tutaj jest cały problem. Zastanawiam się, czy muszę jawnie umieścić każdy z wywołań pobierania obrazów na ich własny wątek ... – bpatrick100

+0

Wystarczy, że wystarczy przydzielić jeden wątek dla wszystkich wywołań pobierania. Jeśli chodzi o połączenia w ogólności, polecam ASIHTTPRequest (http://allseeing-i.com/ASIHTTPRequest/) – kevboh