2013-05-20 13 views
7

Próbuję załadować obraz z lokalnego adresu URL za pomocą następującego:UIImage setImage jest bardzo, bardzo powolny

UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:fileURL]]; 
[self.imageView setImage:image]; 
NSLog(@"imageView set"); 

Więc widzę w konsoli „ImageView ustaw” niemal natychmiast, ale to trwa bardzo długi czas, aby znalazł się w interfejsie użytkownika (czasami kilka minut!).

Każdy pomysł, dlaczego tak się dzieje?

+0

Jaka jest wartość 'fileURL'? W jakim wątku to działa? – Tim

+0

jaki jest rozmiar, rozmiar pliku i format pliku obrazu? – Raptor

+0

fileURL to gif w katalogu dokumentów. Rozmiar pliku obrazu jest mniejszy niż 1-2mb. Funkcja jest wywoływana przez IBAction, ale zakładam, że działa na głównym wątku? –

Odpowiedz

-1

Ładowanie obrazu z NSData zajmuje więcej czasu. Zamiast tego można po prostu użyć następującego kodu:

UIImage *image = [UIImage imageWithContentsOfFile:fileURL]; 

Spróbuj.

+0

Jesteś poważny, naprawdę? O.o – holex

4

Powinieneś załadować instrumenty i zobaczyć, co dokładnie robi.

Na początek należy zrobić, co możliwe, aby uniknąć operacji we/wy na wątku rysunku. Czy są też inne żądania wejścia/wyjścia w tym samym czasie?

A UIImage niekoniecznie musi być pojedynczą reprezentacją bitmapową - może być wspierana przez pamięć podręczną i/lub ładowana leniwie. Dlatego, że "obraz" jest "ustawiony", nie oznacza to, że optymalna mapa bitowa została załadowana do pamięci i przygotowana do renderowania - może być odroczona do czasu żądania renderowania (narysowania).

Profilowanie OTOH powie (ogólnie), dlaczego trwa dłużej niż oczekiwano.

+0

Dzięki. Zdecydowanie powinienem to zrobić. Jedyną rzeczą, która dzieje się na tej stronie jest odtwarzanie wideo ze zdalnego adresu URL. –

+0

@AndyHin cóż, jeśli ten ciężki materiał wideo jest synchroniczny i wykonywany w głównym wątku, może zablokować rysunek ("zamrozić" aplikację), dopóki wideo nie będzie gotowe. "Ustawienie" obrazu nie wyświetli go od razu - po prostu mówi "ten widok trzeba narysować, narysuj go w następnym cyklu rysowania" - ale dużo pracy lub IO w głównym wątku może zablokować ten widok wykresu przerysować wykonanie ponieważ wątek czyta pliki, pobiera filmy wideo lub wiele innych rzeczy, które uniemożliwiają poruszanie się głównego wątku. – justin

-2

Tak próbowałem następujące:

dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:fileURL]]; 
    [self.imageView setImage:image]; 
    NSLog(@"imageView set"); 
}); 

I to jest trochę szybciej. Nie wiem, dlaczego.

+3

To powinno być gorsze, a także niestabilne, ponieważ teraz robisz aktualizacje interfejsu użytkownika w wątku w tle. – rmaddy

+2

Czy próbowałeś używać 'dispatch_get_main_queue' zamiast? Mówisz, że czasami ładowanie lokalnego obrazu zajmuje _minutes_, co często oznacza, że ​​przypadkowo używasz wątku tła podczas używania klas UIKit. – omz

+0

@omz thanks. Próbowałem zamiast tego używać metody dispatch_get_main_queue, która jest jeszcze szybsza. Wydaje się, że to rozwiązało. Gdy IBAction uruchamia funkcję - czy jest ona wykonywana w wątku UI? –

10

Stało się tak, gdy ustawiałem obrazek w wątku tła (w którym pobierałem plik obrazu). Po prostu upewnij się, że twój kod działa w głównym wątku. Obraz zmieni się natychmiast.

// In a background thread... 

UIImage *image = ... // Build or download the image 

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.imageView setImage:image]; // Run in main thread (UI thread) 
});