Cycle Through PDF Documents using Swift for iOS
Use UIPageViewController
to cycle through PDF documents.
//// Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved.//// The Nutrient sample applications are licensed with a modified BSD license.// Please see License for details. This notice may not be removed from this file.//
import PSPDFKitimport PSPDFKitUI
private class PageViewController: UIPageViewController { override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews()
// This is somewhat of a hack to work around the inflexible UIPageViewController // This will extend the content to include the page control indicator. for view in self.view.subviews { if view is UIScrollView { view.frame = self.view.frame } else if view is UIPageControl { self.view.bringSubviewToFront(view) view.backgroundColor = UIColor.clear } } }}
class PageViewControllerExample: Example {
var controller: [UIViewController] = [] var pageViewController: UIPageViewController? var pageIndex: Int { didSet { updateTitle() } }
override init() { pageIndex = 0 super.init() title = "UIPageViewController Example" contentDescription = "Use UIPageViewController to cycle through PDFs" category = .viewCustomization priority = 11 prefersLargeTitles = false }
override func invoke(with delegate: ExampleRunnerDelegate) -> UIViewController { // prepare list of documents you want to present let assetNames: [AssetName] = [.welcome, .about, .web, .annualReport] let documents = assetNames.map { assetName in return AssetLoader.document(for: assetName) } // allocating many PDFViewController instances is memory intensive // if you have many documents, you should switch to a on-demand solution and re-use controllers. controller = documents.map { document in let pdfController = PDFViewController(document: document) { $0.pageTransition = .scrollContinuous $0.scrollDirection = .vertical $0.useParentNavigationBar = true $0.userInterfaceViewMode = .automaticNoFirstLastPage // the scrubber wouldn't work well when we expect horizontal movements to scroll content $0.thumbnailBarMode = .none // background is defined by the page view controller already $0.backgroundColor = UIColor.clear } pdfController.navigationItem.rightBarButtonItems = [pdfController.thumbnailsButtonItem, pdfController.outlineButtonItem, pdfController.searchButtonItem, pdfController.annotationButtonItem] return pdfController }
// set up the page view controller let pageController = PageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [.interPageSpacing: 10]) pageController.dataSource = self pageController.delegate = self pageController.setViewControllers([controller[0]], direction: .forward, animated: false, completion: nil) pageController.view.backgroundColor = #colorLiteral(red: 0.05882352963, green: 0.180392161, blue: 0.2470588237, alpha: 1) pageViewController = pageController pageIndex = 0
// styling as we customize the page indicator to overlay let pageControl = UIPageControl.appearance(whenContainedInInstancesOf: ([PageViewController.self])) pageControl.pageIndicatorTintColor = UIColor.lightGray pageControl.currentPageIndicatorTintColor = UIColor.darkGray UserInterfaceView.appearance(whenContainedInInstancesOf: ([PageViewController.self])).pageLabelInsets = UIEdgeInsets(top: 0, left: 0, bottom: 40, right: 0)
return pageController }
func updateTitle() { // Title is set a bit later in PDFViewController initialization, so we use it from the // document directly. Aternatively, title could be KVO ovserved. guard let pdfController = controller[pageIndex] as? PDFViewController else { return } pageViewController?.title = pdfController.document?.title
// Since we forward the navigationitem from the hosted view controller, we need to explicly update pdfController.updateToolbar(animated: false) }}
extension PageViewControllerExample: UIPageViewControllerDelegate { public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { guard completed, let currentVisibleController = pageViewController.viewControllers?.first, let index = controller.firstIndex(of: currentVisibleController) else { return } // update page index after it updated successfully pageIndex = index }}
extension PageViewControllerExample: UIPageViewControllerDataSource {
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let index = controller.firstIndex(of: viewController), index > 0 else { return nil } return controller[index - 1] }
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let index = controller.firstIndex(of: viewController), index + 1 < controller.count else { return nil } return controller[index + 1] }
// The number of items reflected in the page indicator. public func presentationCount(for pageViewController: UIPageViewController) -> Int { return controller.count }
// The selected item reflected in the page indicator. public func presentationIndex(for pageViewController: UIPageViewController) -> Int { return pageIndex }}
This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.