Embedding PDF View Controllers on iOS
PSPDFKit is designed to work well with UIKit’s container view controller API so that you can easily embed a PDFViewController
inside your custom container view controller implementation. The following steps will guide you through the setup.
Add the PDFViewController as a Child View Controller
First you need to make sure the PDFViewController
is properly added to your container view controller. A good guide on how to do this is Apple’s Implementing a Container View Controller. In our case, we want to add a PDF view controller fullscreen inside the container view controller. So our code to do that looks like this:
let containerController = ... // This is your custom container view controller. let pdfController = ... // This is the configured instance of `PDFViewController` that you want to add. containerController.addChild(pdfController) pdfController.view.frame = containerController.view.bounds // Make the `pdfController` fullscreen in your container controller. pdfController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] // Ensure the `pdfController` resizes along with your container controller. containerController.view.addSubview(pdfController.view) pdfController.didMove(toParent: containerController)
UIViewController *containerController = ...; // This is your custom container view controller. PSPDFViewController *pdfController = ...; // This is the configured instance of `PSPDFViewController` that you want to add. [containerController addChildViewController:pdfController]; pdfController.view.frame = containerController.view.bounds; // Make the `pdfController` fullscreen in your container controller. pdfController.view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); // Ensure the `pdfController` resizes along with your container controller. [containerController.view addSubview:pdfController.view]; [pdfController didMoveToParentViewController:containerController];
For the most part, this information is from Figure 5-1 from the above-mentioned guide, but in addition, we make sure that the controller resizes properly whenever the container view controller’s view changes its bounds. If you are using auto layout inside your container view controller, you may need to alter the code to position and resize the PDF controller correctly.
Non-Fullscreen Presentation
Sometimes the size of the embedded PDFViewController
doesn’t match the size of the container controller. This is usually the case when the container controller adds some decorations around PDFViewController
(e.g. margins, custom navigation bars, or toolbars).
In such a case, you need to be aware that it’s the container’s responsibility to correctly define the size of its child controllers. Here are requirements you need to follow.
Initialization
Make sure the correct frame is set on PDFViewController
’s view before you add it to your view hierarchy. Changing the size of PDFViewController
’s view during the appearance transition might cause UI issues.
If your container has a complex layout, it might be easier to add the PDFViewController
after your container lays out its subviews (viewDidLayoutSubviews()
), so that you’ll already know the correct frame for PDFViewController
’s view.
Size Transitions
Make sure your container controller implements the following:
func size(forChildContentContainer container: UIContentContainer, withParentContainerSize parentSize: CGSize) -> CGSize
- (CGSize)sizeForChildContentContainer:(id<UIContentContainer>)container withParentContainerSize:(CGSize)parentSize;
It should also return the correct size for PDFViewController
. This method is called during size transitions (including rotations), and the result is then passed to PDFViewController
in the following:
func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator;
PDFViewController
uses this size to properly configure itself. Neglecting this might cause layout glitches and break automatic page mode.
Custom Container View Controllers and UINavigationController
If you integrate the PDFViewController
inside your custom view controller, you can still add your custom view controller inside a navigation controller afterward. However, there are a couple of things to keep in mind.
The PDFViewController
will no longer take care of the navigation bar, as the immediate child of the navigation controller is responsible for doing this. You can set useParentNavigationBar
to true
in the PDFConfiguration
and we will do our best to update the navigation bar for you. However, this may not work well in all edge cases and we may require your help.
If you configure the PDFViewController
so that it should hide the navigation bar when the user taps on the screen (PDFConfiguration.shouldHideNavigationBarWithUserInterface
and PDFConfiguration.userInterfaceViewMode
) and you are using opaque navigation bars (i.e. set UINavigationBar.translucent
to false
), make sure to also set extendedLayoutIncludesOpaqueBars
to true
on your container view controller as well. Otherwise, the view of your container view controller will be resized every time the navigation bar changes its visibility state. This also means that the PDFViewController
will get resized in the same way, resulting in an up/down jump of the pages that are currently visible.
In general, when adding a custom container view controller between any kind of UIKit container view controllers (such as UINavigationController
, UITabBarController
, or UISplitViewController
), make sure that the view controller hierarchy is set up correctly. The PDFViewController
’s parent view controller should always be your container view controller in such a case. You should not set the PDF view controller to become a child of the UIKit controller but rather embed it into your custom container view controller’s view hierarchy.
Also keep in mind that everything PDFViewController
would normally do when interacting with the default UIKit container view controllers (e.g. automatically managing navigation bar visibility), it no longer does when it’s embedded in a custom container view controller. From the perspective of the PDFViewController
, your custom container view controller is now responsible for the communication and proper handling of its parent UIKit container view controller.
Samples
If you want to look through more code, there are a couple of samples available in the Catalog under the ViewController Customization section.