When UIAlertController is not enough to show what you want but you still need the modal style, it is up to UIPresentationController and its siblings.
Let’s begin with a single view application. In our case, the existing view controller will be the presenting view controller, responsible for presenting another view controller. Besides, we need a presented view controller, a transitioning delegate, a presentation controller and an animation controller. Sounds a little complicated? Let’s go through them one by one.
Presented View Controller
Presented view controller is the controller presented by presenting view controller. It’s just an ordinary view controller. The only additional thing to do is to set its modalPresentationStyle be UIModalPresentationCustom before presentation. And don’t forget to set Storyboard ID if you use storyboard to configure presented view controller. I set it “PresentedVC”.
Presented view controller has a property transitioningDelegate. It’s responsible for providing presentation controller and animation controller, we set it before the presentation.
Presentation controller is responsible for defining the frame of the presented view and customizing the dimming view during the presentation. We create a class PresentationController which is a subclass of UIPresentationController for it.
Defining the Frame of the Presented View
Both size and position information of the presented view should be provided. Override these two methods:
Of course you can adjust the frame as you need.
Customizing the Dimming View
This part contains creating and animating the dimming view. First, we need to create the dimming view and set it up:
Then implement animating the dimming view for presentation and dismissal:
Deal With Rotation
Without this method, when you rotate the device, just see it by yourself…
Animation controller is also called animator object, it is responsible for creating the animations for transitioning a view controller on or off screen in a fixed amount of time. Usually, we create a presentation animator object and a dismissal animator object respectively in one file. Both animator object need to implement transitionDuration(_:) to set a fixed time and animateTransition(_:) to control the animation of transition.
There are several points need to mention:
transitionContext is the context object containing information about the transition. For examples, the presenting view controller and the presented view controller, the container view.
In the transition of presentation, we get the ending frame rectangle for presented view controller. Why do we know that? Because we set it in presentation controller.
In the transition of dismissal, we get the starting frame rectangle for presented view controller in the same way as before.
The container view is always an ancestor of the presented view controller’s view. We add presented view controller’s view to it before animation of presentation and remove presented view controller’s view from it after animation of dismissal.
Back to Transitioning Delegate
Now that we have PresentationController, PresentationAnimatedTransitioning and DismissalAnimatedTransitioning, the transitioning delegate is very straightforward:
Time to Present
We have all the components ready for the presentation, time to present now: