iOS 8 - Bildschirm leer, nachdem View Controller mit benutzerdefinierter Präsentation geschlossen wurde


68

Wenn Sie verschiedene Ansichtssteuerungen mit schließen UIModalPresentationCustom, wird der Bildschirm nach dem Schließen der Ansichtssteuerung schwarz, als ob alle Ansichtssteuerungen aus der Ansichtshierarchie entfernt worden wären.

Der Übergangsdelegierte ist richtig eingestellt, der animationControllerForPresentedController wird angefordert und korrekt übergeben, und der Übergang ist abgeschlossen, sobald die Animation beendet ist.

Dieser genaue Code funktioniert perfekt, wenn er mit dem iOS 7 SDK kompiliert wird, ist jedoch beim Kompilieren mit iOS 8b5 fehlerhaft


Ich verwende Xcode 6 GM und verhalte ein ähnliches Verhalten, außer dass der Bildschirm weiß ist (mein Fenster hat eine weiße Hintergrundfarbe). Code funktioniert gut in iOS 7. Ich habe die Ansicht mit Reveal überprüft und das Fenster ist einfach leer.
Mark

Xcode 6 GM auch hier und sehen das gleiche Verhalten. Mit dem integrierten View-Exploder finde ich nach dem Übergang nur ein UIWindow und ein UITextEffectsWindow. Alles andere ist weg.
Kevin Sliech

Antworten:


184

Dies liegt daran, dass Sie höchstwahrscheinlich beide Präsentationen hinzufügen

[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]

und das präsentierte

[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]

Zeigen Sie Controller in Ihrem Container an. Zeigen Sie sie in der (void) animateTransition: (id) TransitionContext-Methode Ihres Animations-Controllers an. Da Sie eine benutzerdefinierte modale Präsentation verwenden, wird der Präsentationsansichts-Controller weiterhin unter dem Präsentationsansichts-Controller angezeigt . Da es jetzt noch sichtbar ist, müssen Sie es nicht mehr zur Containeransicht hinzufügen. Fügen Sie stattdessen nur den dargestellten Ansichts-Controller zur containerView hinzu. Sollte in Ihrer animateTransition: -Methode ungefähr so ​​aussehen

UIView *containerView = [transitionContext containerView];
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

// Boolean value to determine presentation or dismissal animation
if (self.presenting){        
    [transitionContext.containerView addSubview:toViewController.view];
    // Your presenting animation code
} else {
    // Your dismissal animation code
}

12
Dies ist die richtige Antwort und sollte akzeptiert werden. In iOS 7 gab es einen Fehler, den sie in iOS 8 behoben haben. Die obige Lösung funktioniert perfekt unter iOS 7 und 8. Vielen Dank, DJSK, dass Sie darauf hingewiesen haben, und einige Zeit damit verbracht haben, herauszufinden, wie ich einen leeren Bildschirm erhalte.
Stas Zhukovskiy

1
Ich stimme @StasZhukovskiy zu. Dies löst das Problem. Ein verbleibendes Problem, das ich finde, ist, dass der präsentierte / entlassene ViewController in iOS7.0 leckt, obwohl nicht 7.1 oder 8 ...
Mike Pollard

3
Anscheinend ist dies nicht die richtige Antwort - laut UIViewControllerContextTransitioningHeader sollten wir die -viewForKeyMethode verwenden, um die Ansichten zu erhalten. Leider ist der Präsentationsstil der UIModalPresentationCustomUrsachen -viewForkeyin einigen Fällen gleich Null, was anscheinend das gewünschte Verhalten ist. Schauen Sie sich bcherrydie Antwort hier an .
DanZimm

1
@DanZimm mit [TransitionContext ViewControllerForKey: UITransitionContextFromViewControllerKey] .view oder [TransitionContext ViewForKey: UITransitionContextFromView] spielt keine Rolle. Sie sind genau das Gleiche. Das Problem bei der Verwendung eines benutzerdefinierten Modalübergangs besteht darin, dass (in iOS8) das Hinzufügen von fromView zum Animationscontroller nach Abschluss der Animation nicht zur ursprünglichen Hierarchie zurückkehrt. Sie können es entweder manuell zurückgeben oder gar nicht hinzufügen.
Scott Kaiser

1
@DJSK Gibt es in Ihrer Post Antwort meiner andere Frage dort ? Vielen Dank
Colas

20

Dies ist die Art von Frage, die die hochstimmigen und akzeptierten Antworten Menschen irreführen. Lange Worte kurz.

Erstens verwenden UIModalPresentationCustom nicht, es ist nicht das, was es klingt. ( Detail )

Zweitens gibt es eine neue Methode zum Abrufen von / zu Ansichten in animateTransition. Verwenden Sie nicht mehr so ​​etwas wie 'fromVC.view'. ( warum )

UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];

//swift
let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)

Jetzt sollte der schwarze Bildschirm verschwinden.


Dies ist definitiv der richtige Weg, um dies zu erreichen, wenn Sie für bestimmte Versionen von iOS wie 8 oder höher entwickeln. Die Antwort, die ich gegeben habe, ist nur eine einfache Möglichkeit, dasselbe zu erreichen, ohne dies überprüfen oder spezifisch sein zu müssen, und gleichzeitig iOS7 zu berücksichtigen.
Scott Kaiser

Wie bekomme ich TransitionContext?
Anita


2

Ich habe den folgenden Code zum Block für den Abschluss des Übergangs hinzugefügt und er wurde für mich behoben.

[UIView animateWithDuration:[self transitionDuration:transitionContext] animations: ^{
    // Animation code

 } completion: ^(BOOL finished) {
     // More of your code

     // Add the following line before completing the transition
    [[[UIApplication sharedApplication] keyWindow] sendSubviewToBack:toViewController.view];

    // Complete the transition
    [transitionContext completeTransition:YES];
}];

2

Vielleicht ist die Ansichtshierarchie mit neuem Xcode fehlerhaft, oder vielleicht ist es etwas anders als iOS8. Dieser Code hat bei mir funktioniert. Fügen Sie es hinzu, während Sie den Controller in der Methode animateTransition: TransitionContext schließen.

[[UIApplication sharedApplication].keyWindow addSubview:toViewController.view];
toViewController.view.userInteractionEnabled = YES;

1
Es ist möglicherweise kein Fehler in iOS, sondern in unserem eigenen Code. Haben Sie modalPresentationStyle auf UIModalPresentationCustom gesetzt, aber die PresentationControllerForPresentedViewController-Methode nicht implementiert? Siehe hier: stackoverflow.com/a/25655575/466965
Lcsky

0

Kurztipp: Stellen Sie sicher, dass Ihr UIViewController "Von" Ihren Erwartungen entspricht.

    NSLog(@" FROM vc %@" , [[transitionContext  viewControllerForKey:UITransitionContextFromViewControllerKey] description]);

Hatte in der Vergangenheit einen ähnlichen Fehler in meinem Code. Sie können ganz einfach den richtigen VC-Kontext "Aus" herausziehen.

  UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];  
  fromView =  [[[fromVC childViewControllers] firstObject]  view];

0

Ich hatte das gleiche Problem, und was das Problem für mich verursacht hat, ist, dass ich den endgültigen Frame des toViewControllers nicht festgelegt habe. Siehe das folgende Beispiel von http://www.appcoda.com/custom-view-controller-transitions-tutorial/

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

    let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
    let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
    let finalFrameForVC = transitionContext.finalFrameForViewController(toViewController)
    let containerView = transitionContext.containerView()
    let bounds = UIScreen.mainScreen().bounds
    toViewController.view.frame = CGRectOffset(finalFrameForVC, 0, bounds.size.height)
    containerView.addSubview(toViewController.view)

    UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: .CurveLinear, animations: {
        fromViewController.view.alpha = 0.5
        toViewController.view.frame = finalFrameForVC
    }, completion: {
        finished in
        transitionContext.completeTransition(true)
        fromViewController.view.alpha = 1.0
    })
} 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.