I am new to Xcode (using 4.3) and am not sure how to save an image to the device's camera roll. All that I have done so far is set up an IBAction for the button to save the image. What library method or function can I use to save an image to the user's camera roll?
5 Answers
You use the UIImageWriteToSavedPhotosAlbum()
function.
//Let's say the image you want to save is in a UIImage called "imageToBeSaved"
UIImageWriteToSavedPhotosAlbum(imageToBeSaved, nil, nil, nil);
Edit:
//ViewController.m
- (IBAction)onClickSavePhoto:(id)sender{
UIImageWriteToSavedPhotosAlbum(imageToBeSaved, nil, nil, nil);
}
Here's an answer for iOS8+ using the Photos framework.
Objective-C:
#import <Photos/Photos.h>
UIImage *snapshot = self.myImageView.image;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:snapshot];
changeRequest.creationDate = [NSDate date];
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"successfully saved");
}
else {
NSLog(@"error saving to photos: %@", error);
}
}];
Swift:
// Swift 4.0
import Photos
let snapshot: UIImage = someImage
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAsset(from: snapshot)
}, completionHandler: { success, error in
if success {
// Saved successfully!
}
else if let error = error {
// Save photo failed with error
}
else {
// Save photo failed with no error
}
})
Here's a link to the Apple documentation.
Don't forget to add the appropriate key/value to your info.plist to request permission to access the photo library:
<key>NSCameraUsageDescription</key>
<string>Enable camera access to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Enable photo library access to select a photo from your library.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Enable photo library access to save images to your photo library directly from the app.</string>
For reference, you can save videos in a similar manner:
UISaveVideoAtPathToSavedPhotosAlbum(videoPath, nil, nil, nil);
You might want to save a video to upload to Instagram, for example:
// Save video to camera roll; we can share to Instagram from there.
-(void)didTapShareToInstagram:(id)sender {
UISaveVideoAtPathToSavedPhotosAlbum(self.videoPath, self, @selector(video:didFinishSavingWithError:contextInfo:), (void*)CFBridgingRetain(@{@"caption" : caption}));
}
- (void) video: (NSString *) videoPath
didFinishSavingWithError: (NSError *) error
contextInfo: (void *) contextInfoPtr {
NSDictionary *contextInfo = CFBridgingRelease(contextInfoPtr);
NSString *caption = contextInfo[@"caption"];
NSString *escapedString = [videoPath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; // urlencodedString
NSString *escapedCaption = [caption stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; // urlencodedString
NSURL *instagramURL = [NSURL URLWithString:[NSString stringWithFormat:@"instagram://library?AssetPath=%@&InstagramCaption=%@", escapedString, escapedCaption]];
[[UIApplication sharedApplication] openURL:instagramURL];
}
Use asImage() to get unique content to save to the camera roll.
If you use asImage() you can save a variety of fun things to the camera roll with just a few lines of code! This can be very powerful if the object has some transparency already incorporated.
asImage() works with UITextView, WKWebView, UIImageView, UIButton, UISlider, UITableView to name some objects (but they may need to be visible when you get the image (having a non zero alpha)). I even use it to capture tiling, but that's loaded into a UIImageView already in my design. I suspect asImage() may work with many more object types too, but I only tried the ones I mentioned.
If it's a UITextView, and you set the background color to .clear then the text gets saved with a transparent background. If your text contains emoji or Memoji, you can now get those images into the camera roll, or into UIImageViews internal to your app. Having Memoji/Emoji with a transparent background in your camera roll where they can be used in any variety of applications is powerful.
Other objects may have some transparency if you crop a photo image to a circle, or set the corner radius to clip off the corners.
Note in my code, pointerToTextObjectSelected is a UITextView
var pointerToTextObjectSelected = UITextView()
// above populated elsewhere
let thisObject = pointerToTextObjectSelected.asImage()
let imageData = thisObject.pngData()
let imageToSave = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(imageToSave!, nil, nil, nil)
// You will need this extension :
extension UIView {
// Using a function since `var image` might conflict with an existing variable
// (like on `UIImageView`)
func asImage() -> UIImage {
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
} else {
UIGraphicsBeginImageContext(self.frame.size)
self.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return UIImage(cgImage: image!.cgImage!)
}
}
}