IOS Swift sharing PDF documents with images

大憨熊 提交于 2019-12-10 12:23:06

问题


I'm getting a weird behaviour when sharing a simple PDF document using Swift on IOS. Basicaly if I create it and share it to be printed the image it should contain is not included. If I first display it using a UIViewController and then share it it's fine. I just don't get why !

Here are the interresting parts of my code :

func getHtml() -> String {
    // Create a HTML document to be printed
    // Save data to file
    let fileName = "noteImage.jpeg"
    let pathToInvoiceHTMLTemplate = Bundle.main.path(forResource: "note", ofType: "html")
    let tmpDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
    let fileURL = tmpDirectoryURL.appendingPathComponent(fileName)
    let mergedImages = getMergedImages()
    //let pngImageData = UIImagePNGRepresentation(image)
    let imageData = UIImageJPEGRepresentation(mergedImages, 1.0)   // if you want to save as JPEG
    try? imageData!.write(to: URL(fileURLWithPath: fileURL.path), options: [.atomic])
    var htmlText = "<html><body><b>Problem Retrieving Note Template</b></body></html>"

    do {
        // Load the note HTML template code into a String variable.
        htmlText = try String(contentsOfFile: pathToInvoiceHTMLTemplate!)

        // Replace the variables in HTML.
        htmlText = htmlText.replacingOccurrences(of: "__PROJECT_NAME__", with: projectName!)
        htmlText = htmlText.replacingOccurrences(of: "__NOTE_NAME__", with: note!.name)
        htmlText = htmlText.replacingOccurrences(of: "__NOTE_IMAGE__", with: "file:"+fileURL.path)
    }
    catch {
        print("Unable to open and use HTML template files.")
    }
    return htmlText
}

func getPdf() -> NSMutableData {
    // Create a PDF document from the HTML to be shared
    // Format HTML
    let fmt = UIMarkupTextPrintFormatter(markupText: getHtml())
    // Assign print formatter to UIPrintPageRenderer
    let render = UIPrintPageRenderer()
    render.addPrintFormatter(fmt, startingAtPageAt: 0)
    // 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")
    // Create PDF context and draw
    let pdfData = NSMutableData()
    UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
    for i in 1...render.numberOfPages {
        UIGraphicsBeginPDFPage();
        let bounds = UIGraphicsGetPDFContextBounds()
        render.drawPage(at: i - 1, in: bounds)
    }
    UIGraphicsEndPDFContext();
    return pdfData
}

@IBAction func shareNote(_ sender: UIBarButtonItem) {
    // Called in direct sharing
    let firstActivityItem = "Text int the message"
    let docToShare = getPdf()        
    let activityViewController : UIActivityViewController = UIActivityViewController(
        activityItems: [firstActivityItem, docToShare], applicationActivities: nil)

    // This lines is for the popover you need to show in iPad
    activityViewController.popoverPresentationController?.barButtonItem = sender

    // This line remove the arrow of the popover to show in iPad
    activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection()
    activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 0, height: 0)

    // Anything you want to exclude
    activityViewController.excludedActivityTypes = [
        UIActivityType.postToWeibo,
        UIActivityType.assignToContact,
        UIActivityType.saveToCameraRoll,
        UIActivityType.addToReadingList,
        UIActivityType.postToFlickr,
        UIActivityType.postToVimeo,
        UIActivityType.postToTencentWeibo,
    ]

    self.present(activityViewController, animated: true, completion: nil)
}

@IBAction func shareDocument(_ sender: UIBarButtonItem) {
    // Called in the preview controller when the HTML is displayed
    let firstActivityItem = "Text in the message"
    let docToShare = getPdf()
    let activityViewController : UIActivityViewController = UIActivityViewController(
        activityItems: [firstActivityItem, docToShare], applicationActivities: nil)

    // This lines is for the popover you need to show in iPad
    activityViewController.popoverPresentationController?.barButtonItem = sender

    // This line remove the arrow of the popover to show in iPad
    activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection()
    activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 0, height: 0)

    // Anything you want to exclude
    activityViewController.excludedActivityTypes = [
        UIActivityType.postToWeibo,
        UIActivityType.assignToContact,
        UIActivityType.saveToCameraRoll,
        UIActivityType.addToReadingList,
        UIActivityType.postToFlickr,
        UIActivityType.postToVimeo,
        UIActivityType.postToTencentWeibo,
    ]

    self.present(activityViewController, animated: true, completion: nil)        
}

Does anybody have a clue ?


回答1:


I found a workaround to my problem : The only solution I found so far is to create a dummy UIWebView that I hide. I load the HTML in the UIWebView and then create the PDF. Here is my code :

    override func viewDidLoad() {
    super.viewDidLoad()

    hiddenWebView.loadHTMLString(htmlText, baseURL: nil)
    hiddenWebView.isHidden = true
}

override func viewDidAppear(_ animated: Bool) {
    pdfDocument = getPdf()
    let tmpDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
    let fileURL = tmpDirectoryURL.appendingPathComponent("document.pdf")
    pdfDocument.write(to: fileURL, atomically: false)
    documentWebView.loadRequest(URLRequest(url: fileURL))
}


来源:https://stackoverflow.com/questions/40022032/ios-swift-sharing-pdf-documents-with-images

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!