2012-04-03 14 views
27

Così sto facendo alcune animazioni personalizzate sul mio controller di navigazione e il modo in cui spinge e fa apparire viewControllers.CALayer - Shadow provoca un calo di prestazioni?

Tutto scorre liscio. Non appena aggiungo il seguente codice (in una sottoclasse di UINavigationController), mi trovo di fronte a un enorme successo in termini di prestazioni. Dopo aver aggiunto un'ombra tutte le animazioni diventano molto scarse. È previsto o sto facendo qualcosa di sbagliato nel codice?

// This code gets called once during NavigationController initialization. 
[self.view setClipsToBounds:NO]; 
[self.view.layer setCornerRadius:5]; 
[self.view.layer setShadowOffset:CGSizeMake(0, 20)]; 
[self.view.layer setShadowColor:[[UIColor yellowColor] CGColor]]; 
[self.view.layer setShadowRadius:20.0]; 
[self.view.layer setShadowOpacity:1]; 

EDIT:

cambiato il mio raggio ombra a 1 ed è ancora lento

+0

Per tutti vale la pena, questo è coperto in modo esplicito nel WWDC 2010 Sessione 425: Core Animation in Practice, parte 2 (https://developer.apple [qui.] .com/devcenter/download.action? path =/videos/wwdc_2010__sd/session_426__core_image_effects_and_optimization.mov) –

risposta

39

È necessario prevedere un rallentamento dall'aggiunta di un'ombra. Un shadowRadius di 20 è molto alto e sarà particolarmente lento.

L'altra chiave per migliorare la velocità di rendering dell'ombra: impostare la proprietà shadowPath. Può aiutare in modo drammatico.

+0

ShadowPath ha fatto il trucco, Il mio raggio di ombra è 10 e funziona ancora bene. – aryaxt

+0

mi hai appena salvato la vita :) –

+2

@NicolasManzini Altri suggerimenti per le prestazioni delle ombre: http://stackoverflow.com/questions/10133109/fastest-way-to-do-shadows-on-ios/10133182#10133182 – aryaxt

2

Sì, l'ombra di sono molto costosi (soprattutto un'ombra così grande - giocare con il raggio e' noteremo che fa un'enorme differenza nel grado di rallentamento che si verifica). Un modo per migliorare le prestazioni è renderlo una volta su uno CGImageContext e visualizzare solo quell'immagine invece di fare ri-renderizzare l'ombra ogni volta che si ridisegna (ma questo non funziona se l'ombra ha bisogno di animare o qualcosa del genere).

+0

Pensi che sarebbe meglio eseguire un png reale e aggiungerlo al mio UIView? – aryaxt

+0

Se questa è una possibilità (cioè conosci la forma/dimensione/qualsiasi cosa dell'ombra in anticipo) allora ti darebbe sicuramente prestazioni migliori. Le immagini sfocate sono molto più veloci delle ombre di rendering. –

+0

Il prerenderato a un'immagine funzionerà finché non sarà necessario modificare la forma dell'ombra. Impostazione –

79
self.view.layer.shouldRasterize = YES; 
self.view.layer.rasterizationScale = UIScreen.mainScreen.scale; 

Recentemente stavo avendo alcuni problemi con le ombre CALayer lento, e così semplice riga di codice sistemato tutto per me!

+0

impressionante, questo lo rende ancora più performante, ora posso avere qualsiasi dimensione di shadowRadius senza avere un impatto sulle prestazioni – aryaxt

+21

Questo ignorerà le immagini retina che potresti avere per l'annotazione. Per risolvere questo problema, aggiungi la seguente riga: self.view.layer.rasterizationScale = [UIScreen mainScreen].scala; – Sean

+2

Sto riscontrando un problema simile a un tableView in cui ogni cella contiene alcuni UILabel e una vista con angoli arrotondati. Ho aggiunto un'ombra al livello che contiene la tabellaView e lo scorrimento diventa instabile. Tuttavia, l'impostazione shouldRasterize = YES ha risolto la choppiness ma ha pixelato la vista (visibilmente sfocata) quindi non è una soluzione accettabile. Ho trovato usando shadowPath invece di shadowOffset ha fatto il trucco. –

13

Utilizzo di shadowPath anziché shadowOffset.

theView.layer.shadowPath = [UIBezierPath bezierPathWithRect:theView.bounds].CGPath; 

Controllare questo post: iphone - Animation's performance is very poor when view's shadow is on

+0

Ha funzionato come un incantesimo, meglio di dovrebbe Rasterizzare che offuscava la vista e tutti i sottolivelli. –

+1

è un modo molto efficiente di testare ... idea con shouldRasterize il lavoro non è così veloce come potrebbe essere necessario. questa risposta è molto meglio! non capisco perché @williamcotton risponda guadagnando così tanti voti ... –

+0

shadowPath è abbastanza buono e veloce, ma come mantenere l'aggiornamento del frame in autolayout? – TomSawyer