2012-05-19 20 views
11

Su iOS, possiamo tracciare una linea in drawRect utilizzandoSu iOS, perché il disegno UIBezierPath non richiede un contesto?

CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextBeginPath (context); 
CGContextMoveToPoint(context, 0, 0); 
CGContextAddLineToPoint(context, 100, 100); 
CGContextStrokePath(context); 

ma possiamo anche disegnare un rettangolo, se togliamo il codice di cui sopra, e basta usare:

domande
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)]; 
[path stroke]; 

Due correlati:

1) Perché lo UIBezierPath non deve ottenere o utilizzare il contesto corrente?

2) Cosa succede se ho due contesti: uno per lo schermo e uno è un contesto bitmap, quindi come dire a quale contesto attingere per UIBezierPath? Ho pensato che potrebbe essere UIGraphicsSetCurrentContext ma non esiste.

risposta

22

UIBezierPath utilizza un contesto. Usa il contesto grafico UIKit corrente. Questa è esattamente la stessa cosa che stai già ricevendo con UIGraphicsGetCurrentContext().

Se si desidera UIBezierPath per utilizzare un contesto diverso, è possibile utilizzare UIGraphicsPushContext(), ma è necessario ricordare di utilizzare UIGraphicsPopContext() al termine.

+1

così avremmo usare 'UIGraphicsPushContext (myBitmapContext);' per iniziare a disegnare in un contesto bitmap? –

+2

@ 動靜 能量: corretto –

5

Su iOS, siamo in grado di tracciare una linea in drawRect utilizzando

ho evidenziato la parte importante di questa affermazione. All'interno di drawRect:, un contesto è già stato impostato per te da UIKit e qualsiasi istruzione di disegno basata su oggetti va direttamente in quel contesto. UIBezierPath utilizza effettivamente tale contesto, non è necessario che venga passato in modo esplicito.

In Cocoa Touch, deve essere sempre presente un contesto di disegno (in questo caso, il contesto verrà infine dipinto sullo schermo). Se non fossi all'interno di drawRect:, dovresti creare tu stesso un contesto.

CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextBeginPath (context); 
CGContextMoveToPoint(context, 0, 0); 

Si noti che la prima chiamata di funzione è GetCurrentContext(). Quando si utilizza l'interfaccia di disegno funzionale di CoreGraphics, è necessario passare un contesto in ogni funzione, ma non ne crei uno qui, stai solo recuperando quello già esistente.

Graphics contexts sono in una pila. Se vuoi disegnare in un contesto che hai creato, lo spinga in pila usando UIGraphicsPushContext() (come già detto da Kevin), quindi torna a quello precedente.

6

Ho pensato che potrebbe essere utile ricordare che CGContextFillRect è ~ 8,5 volte più veloce di usare un UIBezierPath da quello che posso dire (nel caso in cui le prestazioni siano un fattore e presupponendo che non sia necessario utilizzare un UIBezierPath per un disegno più complesso).

ho aggiunto un po 'di tempismo per esempio HazardMap di Apple (http://developer.apple.com/library/ios/#samplecode/HazardMap/Introduction/Intro.html) e il tempo in ms per rect è ~ 0.00064 ms/rect per l'approccio CGContextFillRect rispetto a ~ 0,00543 ms/rect per l'approccio UIBezierPath, presumibilmente b/c il secondo richiede più passaggio del messaggio.

, ad es.Sto confrontando con

CGContextFillRect(ctx, boundaryCGRect); 

rispetto all'utilizzo

UIBezierPath* path = [UIBezierPath bezierPathWithRect:boundaryCGRect]; 
[path fill]; 

nel ciclo interno in HazardMapView (più la suddetta modifiche per spingere/pop contesto che viene passato HazardMapView drawMapRect: zoomScale: InContext :).

ETA

+1

Nota che i numeri sopra riportati provengono dal simulatore iPhone 6.0 in esecuzione su un MacBook Pro (inizio 2012). Eseguendo ciò su un vero iPad3, CGContextFillRect sembra ~ 5.7 volte più veloce rispetto all'utilizzo dell'approccio UIBezierPath. YMMV ovviamente a seconda del dispositivo che si sta utilizzando (le impostazioni di ottimizzazione non sembrano influenzare troppo questo). – ETA

Problemi correlati