Search code examples
iospdfswift2xcode7.1

Save incoming PDF in WebView to Memory


I have a project that is associated with opening PDF files. This is set in the Info.plist. When I get a PDF attachment in email, I can hold my finger on the PDF attachment and then 'Open in' in my app. In my AppDelegate, I have the following added:

func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
    incomingTransfer = URL
    return true
}

incomingTransfer is a Global Variable declared in another ViewController as an NSURL. This ViewController also has a UIWebView and the incomingTransfer loads into it and I'm able to see the new PDF file. My goal is to have a button that allows the user to save the incoming PDF as a PDF. I'm having trouble with this. I thought I had it all figured out, but it wasn't saving as a PDF at all, but rather as a String. Can someone help me please? My goal is to save the incoming PDF file as a PDF to the app memory, preferably in DocumentDirectory. I have a hard time trying to convert Objective C to Swift. My original code to save it was:

    let html = String(incomingFileTransfer)
    let fmt = UIMarkupTextPrintFormatter(markupText: html)

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

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

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

    let pdfData = NSMutableData()
    UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, nil)

    for i in 1...render.numberOfPages() {

        UIGraphicsBeginPDFPage();
        let bounds = UIGraphicsGetPDFContextBounds()
        render.drawPageAtIndex(i - 1, inRect: bounds)
    }

    UIGraphicsEndPDFContext();

    recipeFileName = fileName.text!

    print("File Name Entered: \(recipeFileName)")

    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]

    pdfData.writeToFile("\(documentsPath)/\(recipeFileName).pdf", atomically: true)

Solution

  • I figured it out. I created a class called 'PDFFile'. Within 'PDFFile' are two variables, named var name: String and var url: NSURL. Within my 'IncomingTransfer' ViewController, I have the 'save' button create and save the new file with a typed name from the UITextField and the incomingURL specified in my AppDelegate is assigned to the url variable. Both are then saved to the PDFFile class using NSCoding. I then set a UITableView for it's dataSource from the PDFFile Class array data. I created a segue when the user clicks on the UITableViewCell and that goes to a new ViewController with a UIWebView. This WebView loads the PDF from a urlRequest using the specified url variable, saved from the NSCoding.

    AppDelegate Code:

    // Allows incoming file access (PDF)
    func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
    
        // Transfer incoming file to global variable to be read
    
        if url != "" {
    
            // Load from Mail App
    
            incomingFileTransfer = url
    
            incomingStatus = "Incoming"
    
        } else {
    
            // Regular Load
    
            print("App Delegate: No incoming file")
    
            incomingFileTransfer = nil
    
        }        
    
        return true
    }
    

    IncomingFile code and save button code:

    // MARK: Properties
    var file: PDFFile?
    
    // MARK: Actions
    // Save Button
    let name = fileName.text ?? ""
    
    let url = incomingFileTransfer
    
    file = PDFFile(name: name, url: url)
    
    
    // MARK: NSCoding
    func saveFiles() {
    
        let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(pdfFiles, toFile: PDFFile.ArchiveURL.path!)
    
        if !isSuccessfulSave {
    
            print("Failed to save PDF file")
    
        }
    
    }
    

    Viewing Saved Incoming PDF Later ViewController code: // MARK: Properties @IBOutlet weak var pdfItemWebView: UIWebview!

    var incomingURL: NSURL!
    
    // Within ViewDidLoad
        if let file = file {
    
            pdfFileName.text = file.name
    
            incomingURL = file.url
    
            print("Saved URL: \(incomingURL)")
    
            print("Pending load...")
    
            let request = NSURLRequest(URL: incomingURL!)
    
            pdfItemWebView.loadRequest(request)
    
        }
    

    It was complicated but worked for me. There may be an easier way, but this is what I figured out and its works for my needs.