如何在 swift 中以特定格式创建、编写和保存 pdf 文件

Swi*_*Boy 2 pdf-generation ios swift

在此输入图像描述

我需要在pdf中编写5列的数据数组(图像是为了解释格式),我需要左上角的标题,右上角的图像徽标,换行符,然后显示的行和列图片。下面给出了我为此所做的代码。但是需要进行一些更改才能获得所需的确切格式,请分享一些更好的解决方案,此解决方案中有哪些更改

//Create File

func createPDF() {
        
        let text = gettudentDetails()
        
        let html = "<p>\(text)</p> <hr>"
        let fmt = UIMarkupTextPrintFormatter(markupText: html)

        // 2. Assign print formatter to UIPrintPageRenderer

        let render = UIPrintPageRenderer()
        render.addPrintFormatter(fmt, startingAtPageAt: 0)

        // 3. Assign paperRect and printableRect

        let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
        let printable = page.insetBy(dx: 0, dy: 0)

        render.setValue(NSValue(cgRect: page), forKey: "paperRect")
        render.setValue(NSValue(cgRect: printable), forKey: "printableRect")

        // 4. Create PDF context and draw

        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)

        for i in 1...render.numberOfPages {
            UIGraphicsBeginPDFPage();
            let bounds = UIGraphicsGetPDFContextBounds()
            render.drawPage(at: i - 1, in: bounds)
        }

        UIGraphicsEndPDFContext();

        // 5. Save PDF file

        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]

        guard let outputURL = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("studentRecord").appendingPathExtension("pdf")
        else { fatalError("Destination URL not created") }
        
        pdfData.write(toFile: "\(documentsPath)/studentRecord.pdf", atomically: true)
        loadPDF(filename: "studentRecord.pdf")
    }

//Get formated text
    func gettudentDetails() -> String {
        let image = #imageLiteral(resourceName: "splash_logo")
        let imgData = image.jpegData(compressionQuality: 0.5)

        var text = "<h1>Title Here </h1> <p><img src=\"\(imgData)\" alt=\"\" width=\"60\" height=\"72\" /></p> <hr> <br> </br> Nam &emsp; Father Name &emsp; Id &emsp; Age &emsp; DOB <hr> "
        for record in pdfRecordsList {
            
            let  name = (record.obj?.firstName ?? "")
            let FatherName = record.obj.fatherName ?? ""
            let id = record.obj?.id ?? 0
            let age = record.obj?.age ?? ""
            let dob = record.obj?.dob ?? ""

            text =  text + "<p>" + name + "&emsp;" + FatherName + "&emsp;" + "\(id)" + "&emsp;" + age + "&emsp;" + dob + "</p>"
        }
        
        return text
    }

//Load Pdf
  func loadPDF(filename: String) {
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let url = URL(fileURLWithPath: documentsPath, isDirectory: true).appendingPathComponent(filename)
        let urlRequest = URLRequest(url: url)
        webView.load(urlRequest)
    }
Run Code Online (Sandbox Code Playgroud)

Swi*_*Boy 6

经过大量搜索,阅读了几篇文章,我找到了解决方案,代码在这里,只需复制代码并粘贴到您的控制器,使用资产中添加的图像更改图像名称,然后运行

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {
    
    //MARK: - IBOUTLETS
    let imageLogo = UIImage(named: "logo")
    
    @IBOutlet weak var webView: WKWebView!
    //MARK: - Var& Objects
    
    var nameArr = ["Name1", "Name2", "Name 3", "Name4"]
    var fNameArr = ["FName1", "FName2", "FName3", "FName4"]
    var idArr = ["id 1", "Id 2", "Id 3", "Id 4"]
    var dobArr = ["9/12/1983", "7/23/1976", "7/5/1888", "6/7/1976"]

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.navigationDelegate = self
        createPDF()
        
    }
    // Create and Save Pdf
    func createPDF() {
        
        let text = getDetails()
        
        let html = "\(text)"
        let fmt = UIMarkupTextPrintFormatter(markupText: html)
        
        // 2. Assign print formatter to UIPrintPageRenderer
        
        let render = UIPrintPageRenderer()
        render.addPrintFormatter(fmt, startingAtPageAt: 0)
        
        // 3. Assign paperRect and printableRect
        
        let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
        let printable = page.insetBy(dx: 20, dy: 80)
        
        render.setValue(NSValue(cgRect: page), forKey: "paperRect")
        render.setValue(NSValue(cgRect: printable), forKey: "printableRect")
        
        // 4. Create PDF context and draw
        
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)
        
        for i in 1...render.numberOfPages {
            UIGraphicsBeginPDFPage();
            let bounds = UIGraphicsGetPDFContextBounds()
            render.drawPage(at: i - 1, in: bounds)
        }
        
        UIGraphicsEndPDFContext();
        
        // 5. Save PDF file
        
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        
        guard let outputURL = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("PDFReport").appendingPathExtension("pdf")
        else { fatalError("Destination URL not created") }
        
        pdfData.write(toFile: "\(documentsPath)/PDFReport.pdf", atomically: true)
        drawImageOnPDF(path: "\(documentsPath)/PDFReport.pdf")
        loadPDF(filename: "PDFReport.pdf")
    }
    //Open Pdf on web view
    func loadPDF(filename: String) {
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let url = URL(fileURLWithPath: documentsPath, isDirectory: true).appendingPathComponent(filename)
        let urlRequest = URLRequest(url: url)
        webView.load(urlRequest)
    }
    //get recorded deails in html string
    func getDetails() -> String {
        
        var text = """
<h1>This is Pdf Report</h1>
   
<br>

<table style="width:  100%; border-collapse: collapse;">
    <thead style="border-top: 1px solid black; border-bottom: 1px solid black;">
        <tr>
            <th style="text-align: left; font-weight: 600;"> Name </th>
            <th style="text-align: left; font-weight: 600;"> Name </th>
            <th style="text-align: left; font-weight: 600;"> ID </th>
            <th style="text-align: left; font-weight: 600;"> DOB </th>
            <th style="text-align: left; font-weight: 600;">  </th>

        </tr>
    </thead>
    <tbody style="border-bottom: 1px solid black;">
"""
        for recordIndex in 0..<nameArr.count
 {
            
            let  name = (nameArr[recordIndex])
            
            let fatherName = fNameArr[recordIndex]
            let id = idArr[recordIndex]
            var dob = dobArr[recordIndex]
            
            text = text + """
 <tr>
            <td>\(name)</td>
            <td>\(fatherName)</td>
            <td>\(id)</td>
            <td>\(dob)</td>
        </tr>
 """
        }
        
        text = text + """
            </tbody>
            </table>
            """
        return text
    }
    //pic file from phone directory and draw imge there on given Rect
    func drawImageOnPDF(path: String) {
        
        let pdf = CGPDFDocument(NSURL(fileURLWithPath: path))
        let pageCount = pdf?.numberOfPages
        UIGraphicsBeginPDFContextToFile(path, CGRect.zero, nil)
        for index in 1...pageCount! {
            let page =  pdf?.page(at: index)
            let pageFrame = page?.getBoxRect(.mediaBox)
            UIGraphicsBeginPDFPageWithInfo(pageFrame!, nil)
            let ctx = UIGraphicsGetCurrentContext()
            ctx?.saveGState()
            ctx?.scaleBy(x: 1, y: -1)
            ctx?.translateBy(x: 0, y: -pageFrame!.size.height)
            ctx?.drawPDFPage(page!)
            ctx?.restoreGState()
            
            if index == 1 {
                imageLogo!.draw(in: CGRect(x: 455.2, y: 40, width: 95, height: 65))
            }
            
        }
        UIGraphicsEndPDFContext()
    }
}
Run Code Online (Sandbox Code Playgroud)