Estoy tratando de crear una subclase de CALayer
con una propiedad personalizada index
que puedo animar y cambiar directamente para mostrar una imagen diferente basada en el índice.¿Cómo exactamente subclase CALayer y utiliza una propiedad personalizada?
En la cabecera, que declaró:
@property NSUInteger index;
En la implementación, que hizo caso omiso de needDisplayForKey
:
+ (BOOL)needsDisplayForKey:(NSString *)key
{
if ([key isEqualToString:@"index"])
return YES;
else
return [super needsDisplayForKey:key];
}
Ahora, en el método display
, quiero mostrar una imagen basada en el índice . Sin embargo, durante una animación, el valor de self.index
nunca cambia, así que tengo que consultar el valor de la capa de presentación, contrariamente al ejemplo de Providing CALayer Content by Subclassing:
- (void)display
{
NSUInteger presentationIndex = [(CustomLayer *)[self presentationLayer] index];
self.contents = (id)[[images objectAtIndex:presentationIndex] CGImage];
}
El problema es, si lo hago, no puedo establezca el valor index
directamente fuera de una animación, ya que solo cambiará la capa del modelo, y el método display
consulta explícitamente la capa de presentación.
Si añado un método de inicialización que copia el valor de index
, funciona:
- (id)initWithLayer:(id)layer
{
self = [super initWithLayer:layer];
if (self) {
if ([layer isKindOfClass:[CustomLayer class]])
self.index = [(CustomLayer *)layer index];
}
return self;
}
Sin embargo, después o antes de una animación, siempre hay un problema técnico de imagen 1, ya que la presentación o el valor modelo de Don 't coinciden (dependiendo de si establezco index
en el valor de destino o no).
- Sorprendentemente, parece que el método
drawInContext:
siempre tiene el valor correcto para[self index]
, pero no es el método que desea utilizar ya que acabo de establecer la propiedadcontent
con una imagen. - Tengo diferentes comportamientos según la forma en que implemente la propiedad
index
. Si uso@dynamic index
(que funciona, aunque la documentación no dice que los getters/setters personalizados de propiedad se implementarán dinámicamente), se llama adisplay
cada vez que se cambia el valor deindex
. Si uso@synthesize
o implemente un setter, no se llama adisplay
, por lo que también necesitaría cambiarcontent
en el setter. - ¿Debo usar una variable de instancia? ¿Debería usar la implementación dinámica? ¿O debería usar
setValue:forKey:
en su lugar?
Como puede ver, estoy un poco confundido acerca de cómo obtener el resultado que quiero, y cómo implementar correctamente una subclase de CALayer con una propiedad personalizada. ¡Cualquier ayuda, y explicaciones, serían apreciadas!
"La documentación no dice que captadores de propiedad personalizada/set se aplicarían de forma dinámica" - en realidad, esto es * * documentado en 'CALayer.h':" CALayer implementa el protocolo estándar NSKeyValueCoding para todas las propiedades de Objective C definidas por la clase y sus subclases. Implementa dinámicamente los métodos de acceso faltantes para las propiedades declaradas por subclases ". Por lo tanto, desea utilizar '@ dynamic' si desea' 'needsDisplayForKey:' para que funcione. –
Una gran pregunta ... Estas preguntas "fundamentales" no están suficientemente explicadas en los documentos, y son demasiado esotéricas para todo-pero-la-mayoría-implicada de cómo hacerlo. 'Los de CALayer son tan raros ... Creo que Apple lamenta su implementación de ellos, o tiene demasiadas tecnologías en competencia para molestarse en documentar realmente sus comportamientos a menudo misteriosos. –
Estoy de acuerdo ... Core Animation es trivial de usar para tareas básicas, pero si intentas profundizar, se vuelve esotérico. Como el hecho de que las capas tienen tiempo, además del tiempo de animación. O la misteriosa propiedad 'contents' cuyo tipo es' id', y que puede contener un 'CABackingStore' en caché. O el hecho de que 'CATransition' hereda de' CAAnimation' aún funciona de una manera completamente opaca ... O incluso la relación entre 'UIView' animation blocks y' CALayer' animation ... – Guillaume