【问题标题】:Update PDF View in Swift with PDFKit using existing PDF file使用现有 PDF 文件在 Swift 中使用 PDFKit 更新 PDF 视图
【发布时间】:2022-01-03 20:12:22
【问题描述】:

我遵循本指南https://blog.techchee.com/pdf-composer-app-swiftui/ 能够在 PDF 上绘图,并且我能够加载现有的 PDF 文件并在其上绘图,但现在我的所有绘图都相互重叠。

例如,我可以用一些用户名和公司名填写一次表格,但可能我拼写错误并返回修改。当我再次打开 PdfView 时,它会在现有文本之上绘制,而不是像我预期的那样重新开始。

有没有办法从 PdfDocument 的数据中删除所有绘图并重新开始或类似的方法?

我有 XCode 12 和 Swift 5。谢谢!

这是一个非常简单的例子:

用户类别:

class User {
    var name: String
    var company: String
    
    init(name: String, company: String) {
        self.name = name
        self.company = company
    }
}

创建 PDF:

struct PdfCreation {
    private var user: User
    private var fileName: String
    
    let attributes = [
        NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20)
    ]
    
    let pageRect = CGRect(x: 0, y: 0, width: (8.5 * 72.0), height: (11 * 72.0))
    
    init(user: User) {
        self.user = user
        // can replace filename with any resource saved in project
        // I have a pdf named Check.pdf that I use
        self.fileName = "Check"
    }
    
    private func resourceUrl() -> URL? {
        if let resourceUrl = Bundle.main.url(forResource: self.fileName,
                                             withExtension: "pdf") {
            return resourceUrl
        }
        return nil
    }
    
    func getPdfData() -> Data? {
        if let url = resourceUrl() {
            if let doc = PDFDocument(url: url) {
                
                let page: PDFPage = doc.page(at: 0)!
                
                var mediaBox: CGRect = page.bounds(for: .mediaBox)
                let context = CGContext(url as CFURL, mediaBox: &mediaBox, nil)
                
                UIGraphicsPushContext(context!)
                context!.beginPDFPage(nil)
                
                // Draws the PDF into the context
                page.draw(with: .mediaBox, to: context!)
                
                let flipVertical: CGAffineTransform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: mediaBox.size.height)
                context!.concatenate(flipVertical)
                
                // draw anything you want here
                addName()
                addCompany()
                
                context!.endPDFPage()
                context?.closePDF()
                
                UIGraphicsPopContext()
                let pdfData = doc.dataRepresentation()
                                
                return pdfData
            }
            return nil
        }
        return nil
    }
    
}

extension PdfCreation {
    
    private func addName() {
        let width = 200
        let x = Int(self.pageRect.width) - width
        let y = 80
        let height = 40
        
        let nameRect = CGRect(x: x, y: y, width: width, height: height)
        
        user.name.draw(in: nameRect, withAttributes: attributes)
    }
    
    private func addCompany() {
        let x = 180
        let y = 125
        let width = Int(self.pageRect.width) - x - 100
        let height = 40
        
        let companyRect = CGRect(x: x, y: y, width: width, height: height)
        
        user.company.draw(in: companyRect, withAttributes: attributes)
    }
}

PDF查看

struct PdfViewer: UIViewRepresentable {
    private var data: Data? // pdf data
    
    init(data: Data?) {
        self.data = data
    }
    
    func makeUIView(context: Context) -> PDFView {
        let pageRect = CGRect(x: 0, y: 0, width: (8.5 * 72.0), height: (11 * 72.0))
        let pdfView = PDFView(frame: pageRect)
        
        pdfView.autoScales = true

        // create PDFDocument from the data given
        if let data = self.data {
            pdfView.document = PDFDocument(data: data)
        }
        
        return pdfView
    }

    func updateUIView(_ uiView: PDFView, context: Context) {
        // Empty
    }
}

被导航到的实际视图

struct PdfPreviewViewer: View {
    private var user: User
    private var data: Data?
    
    init(user: User) {
        self.user = user
        self.data = PdfCreation(user: user).getPdfData()
    }
    
    func actionSheet() {
        // share pdf
        
        let activityVC = UIActivityViewController(activityItems: [self.data as Any], applicationActivities: nil)
        UIApplication.shared.windows.first?.rootViewController?.present(activityVC, animated: true, completion: nil)
    }
    
    var body: some View {
        PdfViewer(data: data)
            .navigationTitle(Text("Your PDF"))
            .toolbar() {
                ToolbarItemGroup(placement: .bottomBar) {
                    Spacer()
                    // Share Button
                    Button(action: actionSheet) {
                        Image(systemName: "square.and.arrow.up")
                    }
                }
            }
    }
}

【问题讨论】:

    标签: ios swift pdf swiftui uikit


    【解决方案1】:

    我没有仔细阅读您的所有代码,但这是过去对我有用的:

    extension PDFPage {
        
        func clearAnnotations() {
            // get only our annotations, not the other annotations on the page
            let ourAnnotations = self.annotations.filter { $0.id == MyAnnotation.id} // <-- here adjust for your purpose
            for anno in ourAnnotations {
                self.removeAnnotation(anno)
            }
        }
     
    }
    
     // use it like this to clear all annotations 
     if let page = pdfView?.document?.page(at: 0) {
         page.clearAnnotations()
     }
    

    【讨论】:

      【解决方案2】:

      我从工作狗的回答中获得了一些灵感,并决定从绘图转向 PDFAnnotations,结果比我想象的还要好。我使用本指南绘制注释:

      https://pspdfkit.com/blog/2021/adding-annotations-in-swift-with-pdfkit-vs-pspdfkit/

      通过首先加载我的 PDF,然后将注释添加到 PDFView,我能够提取数据并共享它,并在导航到查看页面时更改注释。

      【讨论】:

        猜你喜欢
        • 2018-11-07
        • 2020-05-16
        • 2014-05-05
        • 1970-01-01
        • 1970-01-01
        • 2016-11-25
        • 1970-01-01
        • 1970-01-01
        • 2019-03-10
        相关资源
        最近更新 更多