2009-10-13 2 views
24

Ho un CABasicAnimation che anima una proprietà di un CALayer ad es. bounds.origin. Voglio essere in grado di osservare la proprietà che cambia nel tempo, ma non ho davvero trovato un metodo che funzioni al 100%.Osservazione delle modifiche alle proprietà animate in un CALayer

  1. Ho provato ad utilizzare KVO (osservazione chiave-valore) su bounds.origin percorso chiave s' il presentationLayer. Il sistema si lamenta che l'oggetto è liberato prima che i suoi osservatori siano liberati, portandomi a pensare che il livello di presentazione sia solo temporaneo. Osservare presentationLayer.bounds.origin come un keypath non funziona.

  2. Ho provato a creare una proprietà su un altro livello e ad animare quella ad es. dichiarando il @property e rendendolo @dynamic su quel livello. Tuttavia questa nuova proprietà viene modificata solo quando si accede al livello di presentazione (ad esempio alla fine dell'animazione), non sembra aggiornarsi mentre l'animazione è in esecuzione.

  3. ho usato needsDisplayForKey sulla proprietà a # 2, che fa scattare gli aggiornamenti durante l'animazione, ma per questi problemi:

    • funziona solo se il CALayer ha struttura diversa da zero. Poiché questo livello potrebbe essere un CAShapeLayer o una sottoclasse, potrebbe avere un frame zero.
    • sembra che si inneschi setNeedsDisplay per quel livello, ma dal momento che in realtà non sto disegnando quel livello solo monitorando la modifica delle proprietà, non voglio causarne il ridisegno.
  4. ho cercato di pianificare un NSTimer, ed entro il callback timer campione Il presentationLayer. Anche questo funziona ma per questi problemi:

    • Il timer sarebbe probabilmente leggermente fuori sincrono con l'aggiornamento dell'animazione.
    • Poiché occasionalmente l'animazione originale viene anticipata da un'altra animazione, è difficile attivare il timer quando l'animazione è in esecuzione e solo quando l'animazione è in esecuzione.

Qualche suggerimento? Tutto questo sarebbe su iPhoneOS 3.0/3.1.

risposta

5

Penso che tu abbia nominato tutte le possibilità. In realtà, non ero nemmeno a conoscenza di # 2 e # 3 e ho scritto the book on Core Animation. ;-)

KVO non è disponibile per queste proprietà. Sarebbe bello se lo fosse, ma credo che la ragione di questo abbia a che fare con il sovraccarico che ci vorrebbe. Il valore si aggiornerebbe molto frequentemente e deve richiamare tutti gli osservatori.

In ogni caso, ho trovato che l'NSTimer è l'approccio più affidabile, ma ora non sono sicuro di quello che hai detto. Cosa ti fa pensare che il timer non sia sincronizzato? Perché è difficile far scattare il timer solo quando l'animazione è in esecuzione? Non puoi semplicemente controllare la condizione che desideri nella richiamata del timer e poi non fare nulla se la condizione non viene soddisfatta?

I migliori saluti.

+1

Gli NSTimer vengono generati senza tener conto di quando i livelli attuali vengono aggiornati, si troveranno sempre leggermente indietro o davanti al passaggio dell'animazione del livello. Quello di cui ho bisogno è di essere notificato * allo stesso tempo * come l'animazione del livello. La soluzione migliore è usare CADisplayLink (solo per iPhone 3.1) o creare un livello artificiale con l'opzione # 3 per essere avvisati. Alla fine, dato che l'ambiente è così dinamico, ho rinunciato all'utilizzo di Core Animation per farlo - ora sto utilizzando un NSTimer o CADisplayLink per eseguire lo scorrimento automatico. –

+0

Quando eseguo lo scorrimento automatico, a volte è presente un'animazione di scorrimento automatico esistente nel livello che sto sostituendo e talvolta l'animazione iniziale deve essere ritardata di 1/2 secondo. Quindi è difficile * sapere * quando l'animazione attuale è in esecuzione. Anche i callback dei delegati CAAnimation non avvengono istantaneamente, quindi c'è la possibilità che qualsiasi codice a seconda di esso non sia sincronizzato con ciò che è già accaduto nel livello animato. –

+2

Vedere ad esempio: http://developer.apple.com/mac/library/qa/qa2004/qa1385.html. Il documento Apple dice "NSTimer è un timer per uso generico, non è un timer collegato al dispositivo di visualizzazione, ma l'intervallo e l'istante in cui il timer ha iniziato a sparare non hanno alcuna relazione con il refresh verticale. di creare un timer a "60.0" Hz è destinato a fallire - il timer andrà alla deriva in relazione alla frequenza di aggiornamento effettiva e si elimineranno o raddoppieranno i frame. Significa anche che il timer chiama l'applicazione in un punto arbitrario nel aggiorna ... " –