UIImage
Swift
save image
iOS development
file handling

How do I save a UIImage to a file?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Saving a UIImage to disk is usually a two-step operation: convert it to Data, then write that data to a file URL. The correct implementation depends on the image format you want, where the file should live, and whether the file is temporary, cached, or user content that should survive app restarts. Once those choices are explicit, the code becomes straightforward and reliable.

Convert the Image to the Right Data Format

UIImage itself is an in-memory object. To save it, you first create a binary representation such as PNG or JPEG.

Use PNG when you need lossless output or transparency:

swift
1import UIKit
2
3func pngData(from image: UIImage) -> Data? {
4    image.pngData()
5}

Use JPEG when file size matters more than exact pixel fidelity and the image does not need transparency:

swift
1import UIKit
2
3func jpegData(from image: UIImage, compression: CGFloat = 0.85) -> Data? {
4    image.jpegData(compressionQuality: compression)
5}

This choice matters because the file extension, MIME type, and visual output should all match the encoding you use.

Pick the Correct App Directory

On iOS, you normally save files under one of three app-managed locations:

  1. documentDirectory for user-generated files that should persist.
  2. cachesDirectory for recreatable files such as thumbnails.
  3. temporaryDirectory for short-lived exports.

This helper builds a destination URL inside the documents directory:

swift
1import Foundation
2
3func documentsURL(filename: String) throws -> URL {
4    let directory = try FileManager.default.url(
5        for: .documentDirectory,
6        in: .userDomainMask,
7        appropriateFor: nil,
8        create: true
9    )
10    return directory.appendingPathComponent(filename)
11}

Avoid hard-coded sandbox paths. Let FileManager resolve the right container path for the running app.

Write the Image Data to Disk

Once you have Data and a destination URL, writing the file is simple. Use .atomic so iOS writes to a temporary file and then swaps it into place.

swift
1import UIKit
2
3enum ImageWriteError: Error {
4    case encodingFailed
5}
6
7func savePNG(_ image: UIImage, filename: String) throws -> URL {
8    guard let data = image.pngData() else {
9        throw ImageWriteError.encodingFailed
10    }
11
12    let fileURL = try documentsURL(filename: filename)
13    try data.write(to: fileURL, options: .atomic)
14    return fileURL
15}

Usage:

swift
1do {
2    let image = UIImage(systemName: "star.fill")!
3    let fileURL = try savePNG(image, filename: "icon.png")
4    print(fileURL.path)
5} catch {
6    print("Save failed:", error)
7}

That covers the core save path for most apps.

Save JPEG Files with Predictable Naming

For photos or exported edits, JPEG is often the better choice. The save logic is the same, only the encoding changes.

swift
1import UIKit
2
3func saveJPEG(_ image: UIImage, filename: String, quality: CGFloat = 0.85) throws -> URL {
4    guard let data = image.jpegData(compressionQuality: quality) else {
5        throw ImageWriteError.encodingFailed
6    }
7
8    let fileURL = try documentsURL(filename: filename)
9    try data.write(to: fileURL, options: .atomic)
10    return fileURL
11}

Keep the filename extension aligned with the encoding. Writing JPEG bytes into a file named .png creates confusion later when the file is reopened or uploaded.

Read the File Back to Confirm the Save

For debugging or tests, verify that the file can be loaded again as an image.

swift
1import UIKit
2
3func loadImage(from url: URL) -> UIImage? {
4    UIImage(contentsOfFile: url.path)
5}

A round-trip read is useful when the image comes from a camera pipeline, a Core Graphics render, or user edits. It confirms that the write path and chosen format are both correct.

Think About Lifetime and Data Protection

Before saving, decide whether the file is user data, cache data, or export data. That decision affects where it belongs and whether you should exclude it from backups or apply stronger file protection. Image persistence is not just a write call. It is a storage policy decision.

If the image is large, avoid unnecessary repeated encoding. Encode once, write once, and keep the returned URL for later reuse.

Common Pitfalls

  • Calling pngData() or jpegData and ignoring the possibility that encoding can fail.
  • Saving JPEG bytes with a .png filename or vice versa.
  • Writing cache-like files into the documents directory and backing up data that should be recreatable.
  • Hard-coding sandbox paths instead of using FileManager to resolve the correct directory.
  • Assuming the save succeeded without testing that the file can be read back from disk.

Summary

  • Convert UIImage to Data with PNG or JPEG depending on the output requirements.
  • Use FileManager to build a destination URL in documents, caches, or temporary storage.
  • Write with .atomic for safer file replacement.
  • Keep the filename extension consistent with the chosen encoding.
  • Validate the result by loading the image back when debugging or testing.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.