Updated September 2026: the 2010 NSFileManager recipe below still describes the right idea, but Swift and modern UIKit give you shorter, safer ways to do the same thing. Both versions are here.
Apps frequently need to persist images: save a photo to the documents directory, load it back on the next launch, delete it when the user removes the item. Here is the minimal round-trip as you would write it today, followed by the original 2010 Objective-C version.
Save / Load / Remove (Swift)
import UIKit
enum ImageStore {
static func url(named name: String) -> URL {
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
.appendingPathComponent("\(name).png")
}
static func save(_ image: UIImage, named name: String) throws {
guard let data = image.pngData() else {
throw CocoaError(.fileWriteUnknown)
}
try data.write(to: url(named: name), options: .atomic)
}
static func load(_ name: String) -> UIImage? {
UIImage(contentsOfFile: url(named: name).path)
}
static func remove(_ name: String) throws {
try FileManager.default.removeItem(at: url(named: name))
}
}
// Usage:
try ImageStore.save(image, named: "avatar")
let loaded = ImageStore.load("avatar")
try ImageStore.remove("avatar")
- Store the file name, never the full path. The documents-directory container path changes between app updates and reinstalls; an absolute path saved by one iOS version may not resolve after the next one.
- PNG vs JPEG:
pngData()is lossless but large for photographs; preferjpegData(compressionQuality: 0.8)for camera images and keep the matching extension in the file name. - Throw errors, don’t log-and-forget. The 2010 version passed
NULLforerror:and NSLogged “image saved” unconditionally — a silent failure was indistinguishable from a save. Swift’sthrowsmakes that impossible.
Capturing the screen in 2026
The OpenGL glReadPixels screenshot routine at the bottom of the original post made sense when apps rendered with OpenGL ES 1.x on a 320×480 display. OpenGL ES itself was deprecated in iOS 12. For a view today, use UIGraphicsImageRenderer:
let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let screenshot = renderer.image { ctx in
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
}
The original 2010 version (Objective-C)
Three NSFileManager-based helpers, one each for saving, loading, and removing:
// Saving an image
- (void)saveImage:(UIImage*)image:(NSString*)imageName {
NSData *imageData = UIImagePNGRepresentation(image);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", imageName]];
[fileManager createFileAtPath:fullPath contents:imageData attributes:nil];
NSLog(@"image saved");
}
// Removing an image
- (void)removeImage:(NSString*)fileName {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", fileName]];
[fileManager removeItemAtPath:fullPath error:NULL];
NSLog(@"image removed");
}
// Loading an image
- (UIImage*)loadImage:(NSString*)imageName {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", imageName]];
return [UIImage imageWithContentsOfFile:fullPath];
}
[self saveImage:myUIImage:@"myUIImageName"];
myUIImage = [self loadImage:@"myUIImageName"];
[self removeImage:@"myUIImageName"];
The screenshot capture was a glReadPixels round-trip — allocate a 320×480×4-byte buffer, read the framebuffer, flip it vertically, and wrap it in a CGImage — followed by UIImageWriteToSavedPhotosAlbum. The core of it, for reference:
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, 320, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// ... flip vertically, build a CGDataProvider + CGImage ...
UIImageWriteToSavedPhotosAlbum([self getGLScreenshot], nil, nil, nil);
The 2010 API surface (NSSearchPathForDirectoriesInDomains, createFileAtPath, UIImagePNGRepresentation) is deprecated or legacy-only now; the Swift version at the top is what you should write today.
1 thought on “Capture Save/Load/Remove Image in documents directory”