Unwind Segue does not reject View Controller with UIModalPresentationCustom

I am presenting a modal presentation controller using a custom transition (by setting its modelPresentationStyle to a UIModalPresentationCustom , providing a transition delegate and a UIViewControllerAnimatedTransitioning object).

In the presented view controller, I have a disconnect button connected to the button. Sege works very well; The IBAction method in the view controller view is called, as well as prepareForSegue in the presented view controller. However, the presented view controller is not rejected, and the corresponding delegate delegation method ( animationControllerForDismissedController: not called.

If, however, I set the presented view controller modalPresentationStyle to UIModalPresentationFullScreen (by default), the view controller rejects properly (this, however, violates my user transition).

I have a complete loss of what to do here. I looked at the Apple documentation and didn’t notice anything, saying that it was necessary to do special things using decoupling when working with custom transitions.

I know that I could call dismissViewControllerAnimated:completion: in the IBAction method for the view presentation controller, but I would prefer to use it as a last resort and make it unwind the work as it should (or at least know why it doesn't work :)).

Any help would be greatly appreciated

Thanks in advance

+7
ios uiviewcontroller unwind-segue
source share
1 answer

It seems that if you use a UIModalPresentationCustom to represent the controller using a custom transition manager, you also need to use a custom transition manager to reject it (which makes sense, I think, since you can do all kinds of weird things in the animator object and UIKit cannot be Sure that just turning off the screen, as usual, will completely restore the original state - I just want him to tell you that clearly ...).

Here is what I did to fix this in my application:

  • override segueForUnwindingToViewController in the parent view controller (the one you move after the dismissal animation) and return an instance of your UIStoryboardSegue , either the one you used for the original transition, or a new separate class
  • If the segue reversal view manager is in the navigation hierarchy, then you need to override this method in the navigation controller.
  • in a call to the perform dismissViewControllerAnimated method
  • the presented view manager should still hold a valid link to the rolling delegate, or you will get EXC_BAD_ACCESS (see DismissViewControllerAnimated EXC_Bad_ACCESS for true ) - so either make the delegate like the strong link described in this thread, or assign a new command before by calling dismissViewControllerAnimated (it is possible that changing modelPresentationStyle to, for example, full-screen mode before leaving, will work, too, but I have not tried)
  • if the dismissal animation should do some non-standard things (mine, fortunately, didn't), override the animationControllerForDismissedController in the transition manager object and return the correct animator
  • If the target view controller is in the navigation hierarchy, you also need to manually place the navigation stack on the target controller before rejecting the presented screen (i.e. target.navigationController!.popToViewController(target, animated: false) )

Full Code Code:

 // custom navigation controller override func segueForUnwindingToViewController(toViewController: UIViewController, fromViewController: UIViewController, identifier: String?) -> UIStoryboardSegue { return CustomSegue( identifier: identifier, source: fromViewController, destination: toViewController ) } // presented VC var customTransitionManager: UIViewControllerTransitioningDelegate? // custom segue override func perform() { let source = sourceViewController as! UIViewController if let target = destinationViewController as? PresentedViewController { let transitionManager = TransitionManager() target.modalPresentationStyle = .Custom target.customTransitionManager = transitionManager target.transitioningDelegate = transitionManager source.presentViewController(target, animated: true, completion: nil) } else if let target = destinationViewController as? WelcomeViewController { target.navigationController!.popToViewController(target, animated: false) target.dismissViewControllerAnimated(true, completion: nil) } else { NSLog("Error: segue executed with unexpected view controllers") } } 
+1
source share

All Articles