En iOS, ¿una vista personalizada no se animará?

En una nueva aplicación de vista única, el siguiente código:

- (void)viewDidAppear:(BOOL)animated { self.fooView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)]; self.fooView.backgroundColor = [UIColor yellowColor]; [self.view addSubview:self.fooView]; [UIView animateWithDuration:2 animations:^{ self.fooView.backgroundColor = [UIColor blueColor]; }]; } 

Animará el background amarillo a azul. El fooView es justo:

 @property (strong, nonatomic) UIView *fooView; 

Pero si se define una class de vista personalizada FooView , y cambio el código anterior reemplazando UIView con FooView , y también defino un -drawRect vacío para FooView , entonces no habrá ninguna animation: el background simplemente se cambia a azul inmediatamente.

No hizo ninguna diferencia si se usa [UIView animateWithDuration: ...] o [FooView animateWithDuration: ...] : no es una animation.

Si dentro de -drawRect , llamo [super drawRect:rect]; , entonces es lo mismo: no hay animation.

Si cambio drawRect para drawRect2 , o si drawRect2 todo el método, entonces la animation funcionará.

(y el -drawRect podría ser necesario, por ejemplo, ¿qué -drawRect si necesitamos dibujar un círculo en la vista personalizada FooView?)

¿Porqué es eso? Además de dar una solución sobre cómo hacer que funcione incluso con un -drawRect , ¿por favor explique lo que estaba sucediendo que no lo hizo animar?

La presencia de drawRect: cambia la forma en que funciona UIView. Solo debe usar drawRect: cuando sea absolutamente necesario y nunca debe tener un drawRect vacío: implementación.

Si el método -drawRect: está presente en su subclass, entonces UIView debe hacer varias cosas antes de poder llamar a este método. Es decir, debe asignar una tienda de respaldo potencialmente costosa en la que se producirá su dibujo personalizado, y debe llenar esta tienda de respaldo con el color de background.

UIView luego llamará a su drawRect: implementación para hacer cualquier dibujo personalizado en la tienda de respaldo, antes de entregar la tienda de respaldo a la GPU. Solo después de todo, su bloque de animation comienza a ejecutarse.

Por lo tanto, al comienzo de su animation, la tienda de respaldo que representa su UIView personalizada ya ha sido pintada con un nuevo color de background.

Si su subclass UIView no tiene drawRect: método, entonces la vista no tiene almacén de respaldo. El color de background es manejado directamente por la GPU, que puede animar muy eficientemente las transiciones entre colors.

Los objects UIView vacíos (sin drawRect: implementación) son bastante ligeros. Su vista personalizada debe estar compuesta por varias subvistas dependiendo de los efectos de animation que desee lograr.

Por ejemplo, la class UITableViewCell está compuesta por muchas subvistas. UITableViewCell en sí es una UIView. Contiene una vista de background y una vista de background seleccionada. Además de eso, está la vista de contenido, y dentro de la vista de contenido hay varias tags de text y vistas de imágenes. Todas estas vistas se combinan para producir la selección y cambiar el tamaño de las animaciones que ve en una UITableView regular.

Use la siguiente línea en el bloque de animation

[self.view addSubview: self.fooView];

Usando la class 'CATransition'. Tendrás que hacer animation. Usando este método

+ (CAAnimation *) setAnimation {}

En lugar de esto, tenemos que crear una nueva class y usar la CATransition y usar los methods de esta class '+ (CAAnimation *) setAnimation'. Tenemos que crear un object para esto y llamar cuando suceda la transición.