3

I want to present a view controller:

  • Modally
  • Using custom transitions
  • At the same time, I want to make sure that when it is dismissed, the view controller behind it is aware of being pushed to the foreground.

My basic idea is to try some different configurations and see which one will lead to viewWillAppear being called on the view controller behind.

Attempt 1

presentedViewController.modalPresentationStyle = .Custom
presentedViewController.transitioningDelegate = someTransitioningDelegate

The results of this approach:

  • The custom transition works perfectly well
  • viewWillAppear does not get called on the view controller behind presentedViewController when I call presentedViewController.dismissViewControllerAnimated(true)

I do want viewWillAppear to be called on the view controller below the one being dismissed, so I did this:

Attempt 2

presentedViewController.modalPresentationStyle = .FullScreen
presentedViewController.transitioningDelegate = someTransitioningDelegate

or

presentedViewController.modalPresentationStyle = .FullScreen
presentedViewController.modalTransitionStyle = .CoverVertical
presentedViewController.transitioningDelegate = someTransitioningDelegate

The results of this approach:

  • viewWillAppear gets called on the view controller behind presentedViewController when dismissing presentedViewController
  • The transition occurs as expected when presenting the view controller.
  • When dismissing the view controller, the background during the transition is black, which is undesirable.

Seems that .FullScreen causes the view controllers behind presentedViewController to be removed from the display hierarchy - which is good because presumably that's what triggers the viewWillAppear call.

Attempt 3

presentedViewController.modalPresentationStyle = .FullScreen
presentedViewController.modalTransitionStyle = .CoverVertical

The results of this are:

  • viewWillAppear gets called on the view controller behind presentedViewController.
  • The background during the transition is the view controller located behind presentedViewController, which is desired.
  • No custom transition.

The project I'm working on is structured in a way that makes it difficult to use delegation (which seems to be the suggested answer here). Making use of NSNotificationCenter is another alternative which lets me call the code that is supposed to be called by viewWillAppear, but from attempt 3, I'm hoping there is a more elegant approach to achieve all these:

  1. Trigger viewWillAppear
  2. Use a custom transition
  3. See the view controller being presented in the background during the transition animation
peco
  • 1,411
  • 3
  • 17
  • 38

2 Answers2

5

Seems Apple considers it foul play to invoke viewWillAppear etc., but it's okay to invoke beginAppearanceTransition and endAppearanceTransition, which in turn will invoke viewWillAppear. I'm going with this.

Community
  • 1
  • 1
peco
  • 1,411
  • 3
  • 17
  • 38
-1

The way I have achieved this in the past is by calling viewWillAppear and viewDidAppear from the transition animator. Here's a simplified example:

public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

    let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
    let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)

    fromVC.viewWillDisappear(true)
    toVC.viewWillAppear(true)

    UIView.animateWithDuration(0.3, animations: {

            //Animations here

            }, completion: { (success) in
                toVC.viewDidAppear(success)
                fromVC.viewDidDisappear(success)
                transitionContext.completeTransition(true)
        })

}

I call the "will" methods before I do animations, and the "did" methods after completion

john_ryan
  • 1,557
  • 1
  • 16
  • 34