¿El momento exacto en que iOS toma la instantánea de la vista al ingresar al fondo?

Tengo un problema al poner mi aplicación de iPhone en segundo plano presionando el botón de salida y luego reiniciando tocando el ícono de inicio en la pantalla de inicio: la vista de la aplicación vuelve a su estado inicial como quiero, pero antes de eso parpadea brevemente el estado anterior de visualización incorrecta en pantalla.

Antecedente

Mi vista principal consiste básicamente en una secuencia de llamadas UIAnimateWithDuration interconectadas. El comportamiento que quiero cada vez que se produce una interrupción es restablecer la animación a su estado inicial (a menos que todas las animaciones hayan terminado y la aplicación haya entrado en la fase final estática), y comenzar desde allí cada vez que la aplicación vuelva al estado activo y visible .

Después de estudiar el tema que aprendí, necesito dos tipos de código de manejo de interrupciones para proporcionar un buen ux: "instantáneo" y "suave". Tengo el método resetAnimation que restablece las propiedades de la vista al estado inicial al instante, y el método pauseAnimation que anima rápidamente al mismo estado, con una etiqueta adicional que indica el desvanecimiento "en pausa" en la parte superior de la vista.

Doble clic en el botón de salida

La razón de esto es el caso de uso del "botón de salida de doble clic", que en realidad no oculta su vista ni lo pone en el estado de fondo, solo se desplaza un poco hacia arriba para mostrar el menú multitarea en la parte inferior. Entonces, restablecer el estado de la vista al instante en este caso simplemente se veía muy feo. La transición animada y decirle al usuario que estás en pausa parecía una mejor idea.

Este caso funciona bien y sin problemas al implementar el método de delegado applicationWillResignActive en mi delegado de aplicaciones y llamar a pauseAnimation desde allí. Manejo el regreso de ese menú multitarea implementando el método de delegado applicationDidBecomeActive y llamando desde allí a mi método resumeAnimation, que desvanece la etiqueta "en pausa" si está allí, y comienza mi secuencia de animación desde el estado inicial.

Todo esto funciona bien, sin parpadeos en ningún lado.

Visitar el reverso

Mi aplicación está construida sobre la plantilla de "utilidad" de Xcode, por lo que tiene una vista invertida para mostrar información / configuración. Me encargo de visitar el otro lado y volver a la vista principal mediante la implementación de estos dos métodos de delegado en mi controlador de vista principal:

(vacío) viewDidDisappear: (BOOL) animada

(vacío) viewDidAppear: (BOOL) animada

Llamo a mi resetAnimation en el método viewDidDisappear y resumeAnimation en viewDidAppear. Todo esto funciona bien, la vista principal es su estado inicial desde el comienzo de la transición al estado visible, sin parpadeo inesperado de estados de animación incorrectos de nada. Pero

Presionando el botón de salida y relanzando desde el ícono de mi aplicación (¡la parte con errores!)

Aquí es donde comienza el problema. Cuando presiono el botón de salida una vez y mi aplicación comienza su transición al fondo, suceden dos cosas. Primero, se llama a applicationWillResignActive aquí también, por lo que también se inicia mi método pauseAnimation. No sería necesario, ya que la transición no necesita ser suave aquí: la vista se vuelve estática y se "aleja" para revelar la pantalla de inicio, pero ¿qué puede hacer? Bueno, tampoco haría ningún daño si pudiera llamar a resetAnimation antes del momento exacto en que el sistema toma la instantánea de la vista.

Anyways, en segundo lugar, se llama a applicationDidEnterBackground en el delegado de aplicaciones. Intenté llamar a resetAnimation desde allí para que la vista estuviera en el estado correcto cuando la aplicación regrese, pero esto no parece funcionar. Parece que ya se ha tomado la "instantánea" y, por lo tanto, cuando toco el ícono de inicio de mi aplicación y la relauch, el estado de vista incorrecto parpadea brevemente en la pantalla antes de que se muestre el estado inicial correcto. Después de eso, funciona bien, las animaciones continúan como se supone que deben hacerlo, pero ese parpadeo feo en ese momento de relanzamiento no desaparecerá, no importa lo que intente.

Fundamentalmente, lo que busco es, ¿en qué momento exacto toma el sistema esta instantánea? Y, en consecuencia, ¿cuál sería el método delegado correcto o el controlador de notificaciones para preparar mi vista para tomar la "foto de recuerdo"?

PD. Luego está default.png, que no parece mostrarse solo en el primer lanzamiento, sino también cuando el procesador está teniendo dificultades o regresando a la aplicación se retrasa brevemente por alguna otra razón. Es un poco feo, especialmente si está volviendo a su vista invertida que se ve totalmente diferente de su vista predeterminada. Pero esta es una característica central de iOS, supongo que ni siquiera debería tratar de averiguar o controlar esa:)

Edit: como la gente pedía el código real y mi aplicación ya se lanzó después de hacer esta pregunta, publicaré algunas aquí. (La aplicación se llama Sweetest Kid, y si quieres ver cómo funciona realmente, está aquí:http: //itunes.apple.com/app/sweetest-kid/id476637106? mt = 8 )

Aquí está mi método PauseAnimation: resetAnimation es casi idéntico, excepto que su llamada de animación tiene cero duración y retraso, y no muestra la etiqueta 'En pausa'. Una razón por la que estoy usando UIAnimation para restablecer los valores en lugar de solo asignar los nuevos valores es que, por alguna razón, las animaciones simplemente no se detuvieron si no usaba UIAnimation. De todos modos, aquí está el método pauseAnimation:

    - (void)pauseAnimation {
    if (currentAnimationPhase < 6 || currentAnimationPhase == 255) { 
            // 6 means finished, 255 is a short initial animation only showing at first launch
        self.paused = YES;
        [UIView animateWithDuration:0.3
                              delay:0 
                            options:UIViewAnimationOptionAllowUserInteraction |
         UIViewAnimationOptionBeginFromCurrentState |
         UIViewAnimationOptionCurveEaseInOut |
         UIViewAnimationOptionOverrideInheritedCurve |
         UIViewAnimationOptionOverrideInheritedDuration
                         animations:^{
                             pausedView.alpha = 1.0;
                             cameraImageView.alpha = 0;
                             mirrorGlowView.alpha = 0;
                             infoButton.alpha = 1.0;
                             chantView.alpha = 0; 
                             verseOneLabel.alpha = 1.0;
                             verseTwoLabel.alpha = 0; 
                             verseThreeLabel.alpha = 0;
                             shine1View.alpha = stars1View.alpha = stars2View.alpha = 0;
                             shine1View.transform = CGAffineTransformIdentity;
                             stars1View.transform = CGAffineTransformIdentity;
                             stars2View.transform = CGAffineTransformIdentity;
                             finishedMenuView.alpha = 0;
                             preparingMagicView.alpha = 0;}
                         completion:^(BOOL finished){
                             pausedView.alpha = 1.0;
                             cameraImageView.alpha = 0;
                             mirrorGlowView.alpha = 0;
                             infoButton.alpha = 1.0;
                             chantView.alpha = 0; 
                             verseOneLabel.alpha = 1.0;
                             verseTwoLabel.alpha = 0; 
                             verseThreeLabel.alpha = 0;
                             shine1View.alpha = stars1View.alpha = stars2View.alpha = 0;
                             shine1View.transform = CGAffineTransformIdentity;
                             stars1View.transform = CGAffineTransformIdentity;
                             stars2View.transform = CGAffineTransformIdentity;
                             finishedMenuView.alpha = 0;
                             preparingMagicView.alpha = 0;
                         }];
        askTheMirrorButton.enabled = YES; 
        againButton.enabled = NO;
        shareOnFacebookButton.enabled = NO;
        emailButton.enabled = NO;
        saveButton.enabled = NO;
        currentAnimationPhase = 0;
        [[cameraImageView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; // To remove the video preview layer
    }
}

Respuestas a la pregunta(5)

Su respuesta a la pregunta