UIViewController - Problem mit benutzerdefinierten Übergängen beim Entlassen

Zusammenfassung

Ich habe einen Inhalt UIViewController, der Einstellungen UIViewController mit einem benutzerdefinierten Übergang darstellt. Die Präsentation ist mitpresentViewController:animated:completion:.

Wenn ich später die Einstellungen mit verwerfedismissViewControllerAnimated:completion:springt der präsentierende Controller plötzlich vor der Präsentation des Einstellungscontrollers in seine Ausgangsposition zurück.

Ich habe eine Lösung dafür auf dem Gerät, aber nicht auf dem Simulator. Ich würde jedoch gerne wissen, was ich falsch mache, anstatt mich in einen Trick zu hacken, der ihn verschwinden lässt. Ich plane auch, diese Animation interaktiv zu gestalten, und ich vermute, dass sich diese Probleme verstärken werden, wenn ich dies tue.

Custom Transition - Haube öffnen

Der gewünschte Effekt ist, dass diepräsentieren Controller fährt den Bildschirm herunter und dievorgeführt Es ist zu sehen, dass der Controller dahinter liegt, von wo aus er angehoben wird, um den Bildschirm auszufüllen. Die Oberseite des präsentierenden Controllers bleibt während der gesamten Nutzungsdauer des präsentierten Controllers auf dem Bildschirm. Es bleibt am unteren Bildschirmrand, aberüber der vorgestellte Controller.

Sie können sich vorstellen, die Motorhaube an einem Auto anzuheben (der Frontpräsentations-Controller), um den Motor dahinter zu sehen (die präsentierten Einstellungen), aber die Motorhaube bleibt für ein wenig Kontext unten sichtbar.

Ich habe vor, dies so zu verfeinern, dass der präsentierende Controller in 3D wirklich perspektivisch anhebt, aber ich bin noch nicht so weit.

Wenn die Einstellungen verworfen werden, sollte der ursprüngliche präsentierende Controller (die Motorhaube) den Bildschirm nach oben schieben und der präsentierte Controller (die Einstellungen) sollte leicht nach hinten sinken (die Motorhaube schließen).

Code

Hier ist die Methode, mit der die Einstellungen auf dem Bildschirm und außerhalb des Bildschirms umgeschaltet werden (sie wird nur von einem UIButton aufgerufen). Sie werden feststellen, dass der Presenting View Controller sich selbst als<UIViewControllerTransitioningDelegate>.

-(void) toggleSettingsViewController
{
  const BOOL settingsAreShowing = [self presentedViewController] != nil;
  if(!settingsAreShowing)
  {
    UIViewController *const settingsController = [[self storyboard] instantiateViewControllerWithIdentifier: @"STSettingsViewController"];
    [settingsController setTransitioningDelegate: self];
    [settingsController setModalPresentationStyle: UIModalPresentationCustom];
    [self presentViewController: settingsController animated: YES completion: nil];
  }
  else
  {
    [self dismissViewControllerAnimated: YES completion: nil];
  }
}

Implementieren<UIViewControllerAnimatedTransitioning>&nbsp;Der Presenting View Controller gibt sich auch nur als das zurück<UIViewControllerAnimatedTransitioning>

-(id<UIViewControllerAnimatedTransitioning>) animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
  return self;
}

-(id<UIViewControllerAnimatedTransitioning>) animationControllerForDismissedController:(UIViewController *)dismissed
{
  // Test Point 1.
  return self;
}

Zum Schluss erhält der Presenting View ControlleranimateTransition::

-(void) animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
  UIViewController *const fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  UIViewController *const toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

  const BOOL isUnwinding = [toController presentedViewController] == fromController;
  const BOOL isPresenting = !isUnwinding;

  UIViewController * presentingController = isPresenting ? fromController : toController;
  UIViewController * presentedController = isPresenting ? toController : fromController;

  if(isPresenting)
  {
    // Add the presented controller (settings) to the view hierarchy _behind_ the presenting controller.
    [[transitionContext containerView] insertSubview: [presentedController view] belowSubview: [presentingController view]];

    // Set up the initial position of the presented settings controller. Scale it down so it seems in the distance. Alpha it down so it is dark and shadowed.
    presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
    presentedController.view.alpha = 0.7;

    [UIView animateWithDuration: [self transitionDuration: transitionContext] animations:^{
      // Lift up the presented controller.
      presentedController.view.transform = CGAffineTransformMakeScale(1.0, 1.0);

      // Brighten the presented controller (out of shadow).
      presentedController.view.alpha = 1;

      // Push the presenting controller down the screen – 3d effect to be added later.
      presentingController.view.layer.transform = CATransform3DMakeTranslation(0,400,0);
     } completion: ^(BOOL finished){
       [transitionContext completeTransition: ![transitionContext transitionWasCancelled]];
     }];
  }
  else
  {
    // Test Point 2.

    // !!!This line should not be needed!!!
    // It resets the presenting controller to where it ought to be anyway.
    presentingController.view.layer.transform = CATransform3DMakeTranslation(0,400,0);

    [UIView animateWithDuration: [self transitionDuration: transitionContext] animations:^{
      // Bring the presenting controller back to its original position.
      presentingController.view.layer.transform = CATransform3DIdentity;

      // Lower the presented controller again and put it back in to shade.
      presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
      presentedController.view.alpha = 0.4;
    } completion:^(BOOL finished) {
      [transitionContext completeTransition: ![transitionContext transitionWasCancelled]];
    }];
  }
}

-(NSTimeInterval) transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
  return 0.5;
}
Problem

Im obigen Code habe ich angegeben!!! Diese Leitung sollte nicht benötigt werden !!!.

Was passiert, ist das zwischenTestpunkt 1&nbsp;undTestpunkt 2&nbsp;Die Bildschirmposition des Presenting View Controllers wird auf die Standard-Vollbildgrenzen zurückgesetzt. Anstatt am unteren Rand des Bildschirms zu sein und wieder sanft zu animieren, springt er plötzlich auf den Bildschirm, um zu positionieren, dass er auch sanft animieren soll!

Ich habe verschiedene Ansätze zur Animation des Presenting View Controllers auf dem Bildschirm ausprobiert:

Ich habe den Rahmen der Ansicht geändert.Ich habe die Transformation der Ansicht geändert.Ich habe die 3D-Transformation der Ansichtsebene geändert.

In allen Fällen umTestpunkt 1Wenn der Übergangsdelegierte gefragt wird, wird der präsentierende Controller wie erwartet eingerichtet. In allen Fällen jedoch beiTestpunkt 2hat der Presenting View Controller die richtige Position verloren und wurde "gelöscht", um die normale Vollbildposition zu haben, auf die ich ihn animieren möchte.

In der obigen Arbeit habe ich den Presenting View Controller explizit dahin versetzt, wo er am Anfang der Animation stehen soll!!! Diese Leitung sollte nicht benötigt werden !!!. Dies scheint auf dem Gerät mit der aktuellen Version von iOS 7 zu funktionieren. Auf dem Simulator ist der Controller jedoch für mindestens einen Frame an der gelöschten Position sichtbar.

Ich bin misstrauisch, dass ich etwas anderes falsch mache und Probleme mit meiner Problemumgehung bekomme, nur um ein anderes Problem zu maskieren.

Irgendwelche Ideen, was los ist? Vielen Dank!