0

I'm saving an image using .writetofile but I don't know how to recover it. This how I save the image:

self.pdfData.writeToURL(NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!.URLByAppendingPathComponent("testgogo.pdf"), atomically: true) // what it is saved as


        self.pdfData.writeToFile("tessst.pdf", atomically: false)
        print(NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!.path!)


        var pdfData: NSData {
            let result = NSMutableData()
            UIGraphicsBeginPDFContextToData(result, frame, nil)
            guard let context = UIGraphicsGetCurrentContext()
  else { return result }

     UIGraphicsBeginPDFPage()
     layer.renderInContext(context)
     UIGraphicsEndPDFContext()
     return result
}

How can I fetch the image back later on ?

Niall Kehoe
  • 379
  • 2
  • 5
  • 18
  • Possible duplicate http://stackoverflow.com/q/29005381/1585121 –  Mar 11 '16 at 16:42
  • None of those answers work for me @Mayerz – Niall Kehoe Mar 11 '16 at 17:07
  • Does this http://stackoverflow.com/questions/24181699/how-to-check-if-a-file-exists-in-the-documents-directory-in-swift/36897617#36897617 not help you? – Scriptable May 29 '16 at 15:50
  • @Scriptable I tried that an it doesn't find the file. Image: http://postimg.org/image/qftzn555n/ – Niall Kehoe May 29 '16 at 17:36
  • then either the file is failing to write or you are looking in the wrong place, can you confirm that the file is being written.. are you definitely writing and reading the exact same file name and extension from the same place? there is obviously something wrong in the logic somewhere – Scriptable May 29 '16 at 17:45
  • I'm saving it like : http://postimg.org/image/rkmrhh1sr/ @Scriptable and recovering it like this : http://postimg.org/image/m6krib1i3/.I doesn't seem to be looking in the right place but I can't figure out why. – Niall Kehoe May 29 '16 at 17:54
  • @Scriptable I was having a look at this question: http://stackoverflow.com/questions/24181699/how-to-check-if-a-file-exists-in-the-documents-directory-in-swift?lq=1 . And for some reason it can find the file! Image: http://s33.postimg.org/7d67ekusf/Screen_Shot_2016_05_29_at_7_03_58_p_m.png – Niall Kehoe May 29 '16 at 18:04
  • because you are calling .path! at the end – Scriptable May 29 '16 at 18:15
  • How can I take it from finding it to recovering it? @Scriptable – Niall Kehoe May 29 '16 at 18:35
  • @NiallKehoe you are writing two files, the first you are writing to the url file testgogo.pdf at your documents directory and the second is being saved at the current directory as tessst.pdf – Leo Dabus May 30 '16 at 01:24
  • So I should keep both those values the same? @LeoDabus Or change it to a file? – Niall Kehoe May 30 '16 at 07:43

4 Answers4

2

Here is an example of how you could do it in Swift 2.x.

It uses the NSData(contentsOfFile: myFilePath) to load the file. The example uses a PNG file.

Directly from my Playground:

import UIKit

/*
 * Creates an UIImage from a UIView
 */
func createImage(fromView view: UIView) -> UIImage {
    UIGraphicsBeginImageContext(view.frame.size)
    let context = UIGraphicsGetCurrentContext()
    view.layer.renderInContext(context!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext();
    return image
}

/*
 * Finds the path in Document folder
 */
func createMyFilePath(forFileName fileName: String) -> String? {
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)
    if let path = paths.first {
        return path + "/\(fileName)"
    }
    return nil
}

/*
 * Main behaviour
 */

// ImageView with Label on it
let imageView = UIImageView(image: UIImage(named: "borat"))
let label = UILabel(frame: imageView.frame)
label.font = UIFont(name: "helvetica", size: 40)
label.text = "Great Success!"
imageView .addSubview(label)

// Find the path where to save
guard let myFilePath = createMyFilePath(forFileName: "borat-with-label.png") else {
    print("Cannot generate file path ☹️")
    exit(0)
}

// Use this to check in finder where your file is saved
print(myFilePath)

// Transform the imageView in UIImage to save it
let imageToSave = createImage(fromView: imageView)

// Get the image as data
guard let imageToSaveAsData = UIImagePNGRepresentation(imageToSave) else {
    print("Cannot transform image to data ☹️")
    exit(1)
}

// Save to Disk!
do{
    try imageToSaveAsData.writeToFile(myFilePath, options: .DataWritingAtomic)
} catch {
    print("Error, cannot write to the location \(myFilePath)")
}

// Load from Disk!
let loadedImageData = NSData(contentsOfFile: myFilePath)

// Check the data is the same
if loadedImageData == imageToSaveAsData {
    print("✌️")
}

// Have a look at the loaded image!
UIImage(data: loadedImageData!)
nicola
  • 96
  • 1
  • 3
1

You will need to remember the URL where you saved the image/pdf that you are storing.

In order to get it back, you can use the NSData class to get the contents of the file at that url.

dataWithContentsOfURL:(NSURL *)aURL is a good place to start.

laynemoseley
  • 258
  • 2
  • 6
  • I'm fetching the image like this: – Niall Kehoe Mar 11 '16 at 17:07
  • let path: String? = NSBundle.mainBundle().pathForResource("testgogo", ofType: "pdf", inDirectory: "DirectoryName/Images") let imageFromPath = UIImage(contentsOfFile: path!)! self.image.image = imageFromPath – Niall Kehoe Mar 11 '16 at 17:07
  • I'm a little bit confused. In your question, you are writing out a `pdf`, buy you actually need an image? – laynemoseley Mar 11 '16 at 17:40
  • I am saving a pdf as png aren't saving properly – Niall Kehoe Mar 11 '16 at 17:46
  • You won't be able to you `UIImage(named:)` if you are saving it as a `pdf` – laynemoseley Mar 14 '16 at 18:30
  • Yeah I know, but it's the recovery process thats not working. I'm hoping to recover it and open it in QLPreviewController. Until the recovery process I can't test it. – Niall Kehoe Mar 15 '16 at 08:55
  • While atomic write operations minimize the risk of data loss due to corrupt or partially-written files, they may not be appropriate when writing to a temporary directory, the user’s home directory or other publicly accessible directories. Any time you work with a publicly accessible file, you should treat that file as an untrusted and potentially dangerous resource. An attacker may compromise or corrupt these files. The attacker can also replace the files with hard or symbolic links, causing your write operations to overwrite or corrupt other system resources. – Leo Dabus May 30 '16 at 01:29
  • Avoid using the writeToURL:atomically: method (and the related methods) when working inside a publicly accessible directory. Instead initialize an NSFileHandle object with an existing file descriptor and use the NSFileHandle methods to securely write the file. – Leo Dabus May 30 '16 at 01:29
1

It looks like the problem might be that you are trying to load the pdf file as an image which won't work. Try this method:

if let pdfURL = NSBundle.mainBundle().URLForResource("myPDF", withExtension: "pdf", subdirectory: nil, localization: nil),data = NSData(contentsOfURL: pdfURL), baseURL = pdfURL.URLByDeletingLastPathComponent  {
    let webView = UIWebView(frame: CGRectMake(20,20,self.view.frame.size.width-40,self.view.frame.size.height-40))
    webView.loadData(data, MIMEType: "application/pdf", textEncodingName:"", baseURL: baseURL)
    self.view.addSubview(webView)
}

Ps I got this code from here: How to Load Local PDF in UIWebView in Swift

Community
  • 1
  • 1
David Breen
  • 247
  • 1
  • 8
  • That piece of code only recovers from a local file in your Xcode project. When there's no pdf in your Xcode project : http://postimg.org/image/kpgktwk2r/ VS When there is a pdf in your Xcode project: http://postimg.org/image/5kuzmburb/ – Niall Kehoe Mar 26 '16 at 11:52
0

Using a slightly modified version of the code in this other answer

I have the following code:

class ViewController: UIViewController {

    @IBOutlet weak var webView: UIWebView!
    lazy var documentsPath = {
       return NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
    }()
    let fileName = "file.pdf"

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        createPDF()

        loadPDF()
    }

    func createPDF() {
        let html = "<b>Hello <i>World!</i></b> <p>Generate PDF file from HTML in Swift</p>"
        let fmt = UIMarkupTextPrintFormatter(markupText: html)

        // 2. Assign print formatter to UIPrintPageRenderer

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

        // 3. Assign paperRect and printableRect

        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")

        // 4. Create PDF context and draw

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

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

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

        UIGraphicsEndPDFContext();

        // 5. Save PDF file

        pdfData.writeToFile("\(documentsPath)/\(fileName)", atomically: true)
    }

    func loadPDF() {

        let filePath = "\(documentsPath)/\(fileName)"
        let url = NSURL(fileURLWithPath: filePath)
        let urlRequest = NSURLRequest(URL: url)
        webView.loadRequest(urlRequest)
    }
}

This code works, it creates a PDF file and then loads the same PDF file into a webView. The only thing that I changed was to create a lazy variable that returns the documents directory and I use a constant for the file path.

You should be able to use the same methods to save and retrieve your PDF file.

enter image description here

Community
  • 1
  • 1
Scriptable
  • 19,402
  • 5
  • 56
  • 72
  • I need to save an image and the value labels on top of it. Should I use code like this : Mountain View to add an image. How should I target each field? – Niall Kehoe May 30 '16 at 16:18
  • you are dealing with some complex logic, I have shown you how to merge images and text using swift in another question already, this question is regarding saving and retrieving a PDF file which I have also shown you. using HTML will work in a similar way, it will overlay elements on top of each other, It will not combine them. I would recommend that you re-create a swift version of the form using UIKit elements and then use the methods shown already to screenshot the view that you have or draw the final result as and when required – Scriptable May 30 '16 at 20:11
  • How should I create that? – Niall Kehoe Jun 20 '16 at 18:13