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.