2011-10-09 15 views
6

Mam widok z bardzo złożoną logiką rysowania (jest to widok mapy, który czerpie z danych GIS). Wykonanie tego rysunku w głównym wątku blokuje interfejs użytkownika i powoduje, że aplikacja przestaje reagować. Chcę przenieść rysunek do wątku tła, na przykład NSSperation.Rysowanie w wątku tła na iOS

Jaki jest najlepszy sposób na strukturę?

Obecnie rysuję do pamięci CGContext pamięci, a następnie przekonwertować go do CGImageRef, które wysyłam do widoku, aby blit na głównym wątku. Niestety zużywa to dużo pamięci i wydaje się, że akceleracja GPU nie jest już używana, ponieważ jest nieco wolniejsza. Czy jest jakiś sposób na bezpośrednie rysowanie widoku z wątku tła? Wiem, że UIKit nie jest bezpieczny w wielu wątkach, ale może jest jakiś sposób na zablokowanie widoku podczas rysowania?

Odpowiedz

1

Nigdy nie spotkałem się z taką sytuacją na iPhonie, ale na komputerze Mac miałem podobny problem tylko raz.

  1. Użyj polecenia CGLayer, aby delegować aktywność rysowania kontekstów offline.
  2. Spróbuj dodać zegar dla bieżącego NSRunLoop i na czasowym interwale wykonuj polecenia graficzne. Powinno to wyglądać mniej więcej tak ...

...

kRenderFPS 25.0 //This is Maximum value 

renderTimer = [[NSTimer timerWithTimeInterval:(1.0/(NSTimeInterval)kRenderFPS) target:viewobject selector:@selector(RenderUI:) userInfo:nil repeats:YES] retain]; 


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSDefaultRunLoopMode]; 


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSModalPanelRunLoopMode]; 


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSEventTrackingRunLoopMode]; 

//In view class 
-(void)RenderUI:(id)param 
{ 
    [self setNeedsDisplayInRect:[self bounds]]; 
} 

To powinno załatwić sprawę.

Spróbuj również przetestować proces i sprawdzić, kto zużywa procesor. Spowoduje to, że interfejs użytkownika będzie reagował i będzie bardzo szybki.

Problem z wydajnością, o którym wspomniałeś, może być spowodowany czymś innym. Spróbuj przetestować proces próbny. Da ci to wgląd w to, kto faktycznie bierze procesor.

+0

Masz na myśli CALayer? –

+1

Nie. CGLayer. http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGLayer/Reference/reference.html – MacGeek

+0

Więc próbuję tego podejścia teraz, ale nawet jeśli uruchamiam NSTimer i uruchomić tylko 50% czasu (uruchamianie w odstępach 0,2 s dla maks. 0,1 s na cykl rysowania) wydaje się, że nadal ignoruje wszystkie zdarzenia interfejsu użytkownika. Czy istnieje jakaś sztuczka? –

6

Poza systemem iOS 4.0, drawing is thread safe. Być może trzeba będzie samemu utworzyć numer CGContext, ale nie ma powodu, dla którego nie można narysować wątku tła.

To powiedziawszy, większość operacji UIKit nie jest. Jeśli chcesz to zrobić, zawsze możesz przygotować się w wątku w tle, a następnie w razie potrzeby użyć performOnMainThread. Jest nawet waitUntilDone. Powiedział, że powinieneś najwyraźniej użyć NSOperation i NSOperationQueue.

+1

Wydaje się, że jest w tym dużo zamieszania, ale jest to poprawna odpowiedź, ponieważ rysowanie systemu iOS 4.0 za pomocą UIKit jest bezpieczne dla wątków. Oto oficjalne ogłoszenie tego: http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS4.html (szukaj "wątku"). –

+0

@Jon Tirsen, dzięki za pomoc uzasadniającą odpowiedź. –