Downloading images using Swift and the URLSession API isn't too difficult. The question is Where do you store the images you download? It is important that you know where you can and cannot store the images your application downloads. A safe place to store images is in the Documents directory of the application container. In this post, I show you how to store an image in the Documents directory using Swift. I promise you that it isn't difficult.

Obtaining the Location of the Documents Directory

You probably know that the system sandboxes applications on Apple's platforms. This implies that you need to be cautious where your application stores images in its container. Obtaining the path or URL to the Documents directory isn't too difficult. We obtain a reference to the shared file manager through the default class method and ask the file manager for the location of the Documents directory. We do this by invoking the urls(for:in:) method.

The urls(for:in:) method accepts the directory we are searching for and a domain mask as its only arguments. The first argument we pass is documentDirectory because we want to obtain the location of the Documents directory. That makes sense. Right? The second argument is less obvious. We pass userDomainMask as the second argument because we search for the Documents directory in the user's home directory.

// Obtaining the Location of the Documents Directory
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)

Even though the urls(for:in:) method returns an array of URL objects, we know that there's only one Documents directory in the application container. We access the first item of the array of URL objects. That URL object points to the Documents directory.

// Obtaining the Location of the Documents Directory
let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]

Storing an Image In the Documents Directory

We have a URL object that points to the Documents directory. The next step is converting the image to a Data object and writing the contents of the Data object to disk. Let's assume we have a UIImage instance and we want to write the image data to the Documents directory.

We start by appending the file name of the image to the URL object that points to the Documents directory. The file name can be anything you want. In this example, we name the file example.png.

// Create URL
let url = documents.appendingPathComponent("example.png")

We then convert the UIImage instance to a Data object by invoking the pngData() method. Because the pngData() method returns an optional Data object, we use optional binding to safely access the Data object.

// Convert to Data
if let data = image.pngData() {

}

To write the image data to the Documents directory, we invoke the write(to:) method on the Data object. Because the write(to:) method is throwing, we wrap the method call in a do-catch statement and prefix it with the try keyword.

// Convert to Data
if let data = image.pngData() {
    do {
        try data.write(to: url)
    } catch {
        print("Unable to Write Image Data to Disk")
    }
}

This is what the complete example looks like.

// Obtaining the Location of the Documents Directory
let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]

// Create URL
let url = documents.appendingPathComponent("image.png")

// Convert to Data
if let data = image.pngData() {
    do {
        try data.write(to: url)
    } catch {
        print("Unable to Write Image Data to Disk")
    }
}

If you add this snippet to, for example, the viewDidLoad() method of a view controller and run the application in the simulator, the image data should be written to the Documents directory. We can verify this by inspecting the application container. I use SimPholders to quickly and easily access the application container. If everything went well, you should see an image with name example.png in the Documents directory of the application container.

How to Store an Image in the Documents Directory in Swift