PDF Page external links ( hyperlink) are not working after rendering PDF content to UIView in Swift iOS

The pdf that has external weblink on the first page for accessing they youtube. When i open it pdf of reader or other apps it will be asked open the youtube. I want to support that functionality in UIView level. I copied PDF content to UIView successfully and but cannot see any action, once i click the external web link.

Here is the my code steps:

  1. Storing pdf file in project level (Doc.pdf)
  2. Take the first page and convert that page to Data. (During the practical scenario, i need to store that value as Data first, it will be needed reuse later, So cannot use PDFPage object for processing directly.).
  3. Binding Data object with CanvasView and override the CanvasView draw method for copying pdf data to UIView. (During practical scenario, I can't use PDFView object, I have to use custom UIView and it will be needed support other customize operation (ex: erasing, cut, copy etc)

Finally, even though all contents are copied successfully, i cannot see any action, once i clicked the external web link.

Here is the code example:

ViewController.Swift

import PDFKit

class ViewController: UIViewController {

    var pdfDocument: PDFDocument?

    override func loadView() {
        super.loadView()
    }

    func getData(pdfPage: PDFPage) -> Data {
        let cropBox = pdfPage.bounds(for: .cropBox)
        var adjustedCropBox = cropBox
        if ((pdfPage.rotation == 90) || (pdfPage.rotation == 270) || (pdfPage.rotation == -90)) {
            adjustedCropBox.size = CGSize(width: cropBox.height, height: cropBox.width)
        }

        let renderer = UIGraphicsPDFRenderer(bounds: adjustedCropBox)
        return renderer.pdfData { (ctx) in
            ctx.beginPage()
            ctx.cgContext.setFillColor(UIColor.white.cgColor)
            ctx.fill(adjustedCropBox)
            pdfPage.transform(ctx.cgContext, for: .cropBox)

            switch pdfPage.rotation {
            case 0:
                ctx.cgContext.translateBy(x: 0, y: adjustedCropBox.height)
                ctx.cgContext.scaleBy(x: 1, y: -1)
            case 90:
                ctx.cgContext.scaleBy(x: 1, y: -1)
                ctx.cgContext.rotate(by: -.pi / 2)
            case 180, -180:
                ctx.cgContext.scaleBy(x: 1, y: -1)
                ctx.cgContext.translateBy(x: adjustedCropBox.width, y: 0)
                ctx.cgContext.rotate(by: .pi)
            case 270, -90:
                ctx.cgContext.translateBy(x: adjustedCropBox.height, y: adjustedCropBox.width)
                ctx.cgContext.rotate(by: .pi / 2)
                ctx.cgContext.scaleBy(x: -1, y: 1)
            default:
                break
            }
            pdfPage.draw(with: .cropBox, to: ctx.cgContext)
        }
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        let fileUrl = Bundle.main.url(forResource: "Doc", withExtension: "pdf")
        guard let fileUrl else {
            return
        }
        pdfDocument = PDFDocument(url: fileUrl)
        let firstPage: PDFPage? = pdfDocument?.page(at: 0)
        print("first page annotation count \(firstPage?.annotations.count)")
        guard let firstPage else {
            return
        }
        let pdfData = getData(pdfPage: firstPage)
        let canvasView = CanvasView(data: pdfData)
        self.view.addSubview(canvasView)

        NSLayoutConstraint.activate([
            canvasView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
            canvasView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 0),
            canvasView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
            canvasView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: 0)
        ])
    }
}

CanvasView.Swift

import PDFKit

class CanvasView: UIView {

    var page: PDFPage?

    init(data: Data) {
        super.init(frame: .zero)
        translatesAutoresizingMaskIntoConstraints = false
        page = loadPDFPage(pdfData: data)
    }

    init(pdfPage: PDFPage){
        super.init(frame: .zero)
        translatesAutoresizingMaskIntoConstraints = false
        page = pdfPage
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func loadPDFPage(pdfData: Data) -> PDFPage? {

        guard let document = PDFDocument(data: pdfData) else {
            return nil
        }
        return document.page(at: 0)
    }

    override func draw(_ layer: CALayer, in ctx: CGContext) {
        guard let page else {
            return
        }
        print("num of annotations - \(page.annotations.count)")
        if let cgPDFPage = page.pageRef {
            let cropBoxBounds = page.bounds(for: .cropBox)
            print(page.displaysAnnotations)

            let scaleX = layer.bounds.width / cropBoxBounds.width
            let scaleY = layer.bounds.height / cropBoxBounds.height

            ctx.saveGState()

            ctx.scaleBy(x: scaleX, y: scaleY)
            ctx.translateBy(x: -cropBoxBounds.origin.x, y: cropBoxBounds.height + cropBoxBounds.origin.y )
            ctx.scaleBy(x: 1, y: -1)
            ctx.setFillColor(UIColor.white.cgColor)
            ctx.fill(cropBoxBounds)
            ctx.drawPDFPage(cgPDFPage)
            ctx.restoreGState()
        }
    }

    override func draw(_ rect: CGRect) {}
}

Here the project

Special Note: Once i loaded PDFPage from url, it has two link annotations. Once i created PDFPage from Data in CavansView, i cannot see any PDF annotations and it is empty. So I assume, during data conversion process, annotations will not be considered. even though i pass original PDFPage object directly instead of Data, link click actions are not worked.

So i need to someone help from how we send PDFAnnotation object data to Data object and How we can support web link behaviour as we expected.

Please, help me to resolve this case and i really appreciate your feedback and help.

PDF Page external links ( hyperlink) are not working after rendering PDF content to UIView in Swift iOS
 
 
Q