2011-10-09 9 views
6

Ho una vista con una logica di disegno molto complessa (è una vista mappa che richiama i dati GIS). Facendo questo disegno sul thread principale si blocca l'interfaccia utente e l'app non risponde. Voglio spostare il disegno su un thread in background con ad esempio una NSOperation.Disegno in un thread in background su iOS

Qual è il modo migliore per strutturare questo?

Attualmente sto disegnando su una memoria CGContext e poi lo converto in un CGImageRef che mando alla vista per blit sul thread principale. Sfortunatamente questo consuma molta memoria e sembra che l'accelerazione della GPU non sia più utilizzata poiché è un po 'più lenta. C'è un modo per disegnare direttamente alla vista da un thread in background? So che UIKit non è sicuro multi-thread ma forse c'è un modo per bloccare la vista mentre sto facendo il disegno?

risposta

1

Non mi sono mai imbattuto in questa situazione su iPhone ma su Mac ho avuto un problema simile una volta.

  1. Utilizzare CGLayer per delegare l'attività di disegno di contesti offline.
  2. Provare a aggiungere timer per NSRunLoop corrente e in base all'intervallo di tempo eseguire i comandi grafici. Dovrebbe essere qualcosa di simile ...

...

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]]; 
} 

Questo dovrebbe fare il trucco.

Provare anche a campionare il processo e controllare chi sta consumando la CPU. Ciò renderà l'interfaccia utente reattiva e molto veloce.

Il problema di prestazioni che hai citato è dovuto a qualcos'altro. Prova a processo di esempio della cpu. Vi darà un'idea di chi sta effettivamente prendendo la CPU.

+0

Intendi CALayer? –

+1

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

+0

Quindi sto provando questo approccio ora, ma anche se corro con un NSTimer ed eseguo solo il 50% del tempo (eseguito su intervalli di 0,2 secondi per un massimo di 0,1 secondi per ciclo di disegno) sembra che stia ancora ignorando tutti gli eventi dell'interfaccia utente. C'è un trucco per questo? –

6

Oltre iOS 4.0, drawing is thread safe. Potrebbe essere necessario creare uno CGContext autonomamente, ma non c'è motivo per cui non si possa disegnare su un thread in background.

Detto questo, la maggior parte delle operazioni UIKit non lo sono. Se è necessario, è possibile prepararsi sempre in un thread in background e quindi utilizzare performOnMainThread quando necessario. C'è anche waitUntilDone. Detto questo, dovresti usare NSOperation e NSOperationQueue, apparentemente.

+1

Sembra esserci molta confusione su questo, ma questa è la risposta corretta, dato che il disegno di iOS 4.0 con UIKit è thread-safe. Ecco l'annuncio ufficiale di questo: http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS4.html (cerca "thread"). –

+0

@Jon Tirsen, grazie per l'aiuto a sostegno della risposta. –