ZoomingPDFViewerSwift/ZoomingPDFViewer/TiledPDFScrollView.swift
/* |
Copyright (C) 2017 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
UIScrollView subclass that handles the user input to zoom the PDF page. This class handles swapping the TiledPDFViews when the zoom level changes. |
*/ |
import UIKit |
class TiledPDFScrollView: UIScrollView, UIScrollViewDelegate { |
// Frame of the PDF |
var pageRect = CGRect() |
// A low resolution image of the PDF page that is displayed until the TiledPDFView renders its content. |
var backgroundImageView: UIView! |
// The TiledPDFView that is currently front most. |
var tiledPDFView: TiledPDFView! |
// The old TiledPDFView that we draw on top of when the zooming stops. |
var oldTiledPDFView: TiledPDFView! |
// Current PDF zoom scale. |
var PDFScale = CGFloat() |
// a reference to the page being drawn |
var tiledPDFPage: CGPDFPage! |
func initialize() |
{ |
decelerationRate = UIScrollViewDecelerationRateFast |
delegate = self |
layer.borderColor = UIColor.lightGray.cgColor |
layer.borderWidth = 5 |
minimumZoomScale = 0.25 |
maximumZoomScale = 5 |
backgroundImageView = UIView(frame: frame) |
oldTiledPDFView = TiledPDFView(frame: pageRect, scale: PDFScale) |
} |
required init?(coder aDecoder: NSCoder) |
{ |
super.init(coder: aDecoder) |
initialize() |
} |
override init(frame: CGRect) |
{ |
super.init(frame: frame) |
initialize() |
} |
func setPDFPage(_ newPDFPage: CGPDFPage?) |
{ |
// note: calls to CGPDFPageRetain and CGPDFPageRelease in the Objective-C version are not necessary here because CF objects are automatically memory managed in Swift. |
tiledPDFPage = newPDFPage |
// PDFPage is null if we're requested to draw a padded blank page by the parent UIPageViewController |
if tiledPDFPage == nil |
{ |
pageRect = bounds |
} |
else |
{ |
pageRect = tiledPDFPage.getBoxRect(CGPDFBox.mediaBox) |
PDFScale = frame.size.width / pageRect.size.width |
pageRect = CGRect(x: pageRect.origin.x, y: pageRect.origin.y, width: pageRect.size.width * PDFScale, height: pageRect.size.height * PDFScale) |
} |
// Create the TiledPDFView based on the size of the PDF page and scale it to fit the view. |
replaceTiledPDFViewWithFrame(pageRect) |
} |
// Use layoutSubviews to center the PDF page in the view. |
override func layoutSubviews() |
{ |
super.layoutSubviews() |
// Center the image as it becomes smaller than the size of the screen. |
let boundsSize:CGSize = bounds.size |
var frameToCenter:CGRect = tiledPDFView.frame |
// Center horizontally. |
if frameToCenter.size.width < boundsSize.width |
{ |
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2 |
} |
else |
{ |
frameToCenter.origin.x = 0 |
} |
// Center vertically. |
if frameToCenter.size.height < boundsSize.height |
{ |
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2 |
} |
else |
{ |
frameToCenter.origin.y = 0 |
} |
tiledPDFView.frame = frameToCenter |
backgroundImageView.frame = frameToCenter |
/* |
To handle the interaction between CATiledLayer and high resolution screens, set the tiling view's contentScaleFactor to 1.0. |
If this step were omitted, the content scale factor would be 2.0 on high resolution screens, which would cause the CATiledLayer to ask for tiles of the wrong scale. |
*/ |
tiledPDFView.contentScaleFactor = 1.0 |
} |
/* |
A UIScrollView delegate callback, called when the user starts zooming. |
Return the current TiledPDFView. |
*/ |
func viewForZooming(in scrollView: UIScrollView) -> UIView? |
{ |
return tiledPDFView |
} |
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) |
{ |
// Remove back tiled view. |
oldTiledPDFView.removeFromSuperview() |
// Set the current TiledPDFView to be the old view. |
oldTiledPDFView = tiledPDFView |
} |
/* |
A UIScrollView delegate callback, called when the user begins zooming. |
When the user begins zooming, remove the old TiledPDFView and set the current TiledPDFView to be the old view so we can create a new TiledPDFView when the zooming ends. |
*/ |
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) |
{ |
// Set the new scale factor for the TiledPDFView. |
PDFScale *= scale |
replaceTiledPDFViewWithFrame(oldTiledPDFView.frame) |
} |
func replaceTiledPDFViewWithFrame(_ frame: CGRect) |
{ |
// Create a new tiled PDF View at the new scale |
let newTiledPDFView = TiledPDFView(frame: frame, scale: PDFScale) |
newTiledPDFView.pdfPage = tiledPDFPage |
// Add the new TiledPDFView to the PDFScrollView. |
addSubview(newTiledPDFView) |
tiledPDFView = newTiledPDFView |
} |
} |
Copyright © 2017 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2017-04-27