Cambiar un marco en viewDidLayoutSubviews

Cuando se muestra por primera vez la vista de un controller de visualización, quiero ejecutar una animation en la que todos los elementos del controller de visualización se deslicen desde el exterior de la pantalla hasta sus posiciones naturales. Para lograr esto, hago subview.frame.origin.y += self.view.frame.size.height en viewDidLayoutSubviews . También probé viewWillAppear , pero no funciona en absoluto. Luego los subview.frame.origin.y -= self.view.frame.size.height a sus posiciones naturales con subview.frame.origin.y -= self.view.frame.size.height en viewDidAppear .

El problema es que viewDidLayoutSubviews se viewDidLayoutSubviews varias veces a lo largo de la vida útil del controller de vista. Como tal, cuando se muestran cosas como mostrar el keyboard, todo mi contenido se reemplaza fuera de la vista nuevamente.

¿Hay un método mejor para hacerlo? ¿Debo agregar algún tipo de indicador para verificar si la animation ya se ha ejecutado?

EDITAR: aquí está el código. Aquí estoy llamando prepareAppearance en viewDidLayoutSubviews , que funciona, pero viewDidLayoutSubviews se llama varias veces a lo largo de la vida útil del controller.

 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; [self prepareAppearance]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self animateAppearance]; } - (NSArray *)animatableViews { return @[self.createAccountButton, self.facebookButton, self.linkedInButton, self.loginButton]; } - (void)prepareAppearance { NSArray * views = [self animatableViews]; NSUInteger count = [views count]; for (NSUInteger it=0 ; it < count ; ++it) { UIView * view = [views objectAtIndex:it]; CGRect frame = view.frame; // Move the views outside the screen, to the bottom frame.origin.y += self.view.frame.size.height; [view setFrame:frame]; } } - (void)animateAppearance { NSArray * views = [self animatableViews]; NSUInteger count = [views count]; for (NSUInteger it=0 ; it < count ; ++it) { __weak UIView * weakView = [views objectAtIndex:it]; CGRect referenceFrame = self.view.frame; [UIView animateWithDuration:0.4f delay:0.05f * it options:UIViewAnimationOptionCurveEaseOut animations:^{ CGRect frame = weakView.frame; frame.origin.y -= referenceFrame.size.height; [weakView setFrame:frame]; } completion:^(BOOL finished) { }]; } } 

Si necesita animar algo cuando aparezca la vista y luego no toque las subidas posteriores, sugiero lo siguiente:

  • No cambie / toque viewDidLayoutSubviews
  • Agregue lógica para mover elementos fuera de la pantalla (a su position inicial antes de la animation) en viewWillAppear
  • Agregue lógica para animar elementos en su position correcta en viewDidAppear

ACTUALIZACIÓN :

Si está utilizando el layout automático (que es muy bueno), no puede animar vistas cambiando sus frameworks directamente (porque el layout automático ignoraría eso y los cambiaría de nuevo). Lo que debe hacer es exponer los puntos de venta a las restricciones responsables de la position Y (en su caso) y cambiar esas restricciones en lugar de establecer frameworks.

Además, no olvide include la llamada a [weakView layoutIfNeeded] después de actualizar las restricciones en el método de animation.

Hice ambas cosas en viewDidAppear: Parece que cuando se llama a viewDidAppear: la vista no es visible, sino que está a punto de hacerlo. Por lo tanto, los elementos de la interfaz de usuario nunca aparecen en su position inicial si son reemplazados allí.