Saving an Image to Photos Library Using Swift 2.0

How to save picture to iPhone photo library?

You can use this function:

UIImageWriteToSavedPhotosAlbum(UIImage *image, 
id completionTarget,
SEL completionSelector,
void *contextInfo);

You only need completionTarget, completionSelector and contextInfo if you want to be notified when the UIImage is done saving, otherwise you can pass in nil.

See the official documentation for UIImageWriteToSavedPhotosAlbum().

How to save image to custom album?

I came up with this singleton class to handle it:

import Photos

class CustomPhotoAlbum {

static let albumName = "Flashpod"
static let sharedInstance = CustomPhotoAlbum()

var assetCollection: PHAssetCollection!

init() {

func fetchAssetCollectionForAlbum() -> PHAssetCollection! {

let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", CustomPhotoAlbum.albumName)
let collection = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions)

if let firstObject: AnyObject = collection.firstObject {
return collection.firstObject as! PHAssetCollection
}

return nil
}

if let assetCollection = fetchAssetCollectionForAlbum() {
self.assetCollection = assetCollection
return
}

PHPhotoLibrary.sharedPhotoLibrary().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle(CustomPhotoAlbum.albumName)
}) { success, _ in
if success {
self.assetCollection = fetchAssetCollectionForAlbum()
}
}
}

func saveImage(image: UIImage) {

if assetCollection == nil {
return // If there was an error upstream, skip the save.
}

PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let assetChangeRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(image)
let assetPlaceholder = assetChangeRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: self.assetCollection)
albumChangeRequest.addAssets([assetPlaceholder])
}, completionHandler: nil)
}

}

When you first instantiate the class, the custom album will be created if it doesn't already exist. You can save an image like this:

CustomPhotoAlbum.sharedInstance.saveImage(image)

NOTE: The CustomPhotoAlbum class assumes the app already has permission to access the Photo Library. Dealing with the permissions is a bit outside the scope of this question/answer. So make sure PHPhotoLibrary.authorizationStatus() == .Authorize before you use it. And request authorization if necessary.

Error Saving Image to Photo Library iOS/Mac Catalyst App Swift

I was able to save the images to MacOS through this Mac Catalyst App using the following code in Swift;

func insertImageMac(image : UIImage, albumName : String) {
let collection = fetchAssetCollectionWithAlbumName(albumName: albumName)
if collection == nil {
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
}, completionHandler: {(success, error) in
if error != nil {
print("Error: " + error!.localizedDescription)
}

if success {
let newCollection = self.fetchAssetCollectionWithAlbumName(albumName: albumName)
self.insertImage(image: image, intoAssetCollection: newCollection!)
}
}
)
} else {
self.insertImage(image: image, intoAssetCollection: collection!)
}
}

func fetchAssetCollectionWithAlbumName(albumName : String) -> PHAssetCollection? {

let fetchOption = PHFetchOptions()
fetchOption.predicate = NSPredicate(format: "title == '" + albumName + "'")

let fetchResult = PHAssetCollection.fetchAssetCollections(
with: PHAssetCollectionType.album,
subtype: PHAssetCollectionSubtype.albumRegular,
options: fetchOption)
let collection = fetchResult.firstObject as? PHAssetCollection

return collection
}

func insertImage(image : UIImage, intoAssetCollection collection : PHAssetCollection) {
PHPhotoLibrary.shared().performChanges({
let creationRequest = PHAssetCreationRequest.creationRequestForAsset(from: image)
let request = PHAssetCollectionChangeRequest(for: collection)
if request != nil && creationRequest.placeholderForCreatedAsset != nil {
request!.addAssets([creationRequest.placeholderForCreatedAsset!] as NSFastEnumeration)
}

},

completionHandler: { (success, error) in
if error != nil {
print("Error: " + error!.localizedDescription)
let ac = UIAlertController(title: "Save error", message: error!.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Done", style: .default))
self.present(ac, animated: true)
} else {
let ac = UIAlertController(title: "Save success", message: "Image saved", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Done", style: .default))
self.present(ac, animated: true)
}
}
)
}

...and calling it inside my button function with the image;

insertImageMac(image: myImage, albumName: "AlbumName")

Take a screenshot and then save it to the camera roll. Swift 4.2, Xcode 10

You should check the console for the below error,

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.

So just add the NSPhotoLibraryAddUsageDescription key in Info.plist file.

How can I save SDWebImageSwiftUI to Photos in Swift?

Hopefully this will help others to achieve similar goal like mine, since I don't see a lot of answers on sdwebimage I had to take the time to write an answer my self. So finally after hours of searching and testing different approaches, in short you convert url image to UIImage and save that to the device.

I was able to achieve my goal by the following code:

First I created an image saver class:

import Foundation
import SwiftUI

extension UIImage {
var jpeg: Data? { jpegData(compressionQuality: 1) } // QUALITY min = 0 / max = 1
var png: Data? { pngData() }
}

extension Data {
var uiImage: UIImage? { UIImage(data: self) }
}

class ImageSaver: NSObject {
func writeToPhotoAlbum(image: UIImage) {
UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveError), nil)
}

@objc func saveError(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
print("save finished")
}
}

thats based on this repo: https://github.com/krish-21/Fiftygram

Then added these two variables and function in my ContentView.swift

@State var imageData: UIImage?
@State private var imageSaved: Bool = false

// save Image to Photo Album
func saveImage() {
let imageSaver = ImageSaver()
if let uiImage = imageData {
imageSaver.writeToPhotoAlbum(image: uiImage)
imageSaved = true
}
}

Then called this inside the save button or tap gesture:

imageData = UIImage(data: try! Data(contentsOf: URL(string: imageName.fileLink)!))!

saveImage()

So my code looks like this, can't post the full code because of project privacy:

import Foundation
import SwiftUI
import SDWebImageSwiftUI

struct ContentView: View {
@State var imageData: UIImage?
@State private var imageSaved: Bool = false

// save Image to Photo Album
func saveImage() {
let imageSaver = ImageSaver()
if let uiImage = imageData {
imageSaver.writeToPhotoAlbum(image: uiImage)
imageSaved = true
}
}

var body: some View {
VStack {
ForEach(self.moodboardImages, id: \.self) { imageName in
WebImage(url: URL(string: imageName.fileLink))
.resizable()
.aspectRatio(contentMode: .fit)
.pinchToZoom()
.onTapGesture {
//Save to Library ?
imageData = UIImage(data: try! Data(contentsOf: URL(string: moodboardImages[index].fileLink)!))!
saveImage()
}
}
}
// alert the user after image is saved
.alert(isPresented: $imageSaved) {
Alert(title: Text("Saved"), message: Text("Moodboard image has been saved to Photos"), dismissButton: .default(Text("Done")))
}
}
}

Also after some digging on sdwebimage GitHub issues tab and version pull requests I was able to find this:

You can get the raw image and data objects from WebImage by adding .onSuccess with the following param.

WebImage(url: URL(string: imageName.fileLink))
.resizable()
.aspectRatio(contentMode: .fit)
.pinchToZoom()
.onSuccess {
(image, data, cacheType) in
// you can use image or data to save it, or do whatever you want with it, example:
// saveImage(data) or saveImage(image) , depending on your needs or code
}

Note Works with SDWebImageSwiftUI 2.0+



Related Topics



Leave a reply



Submit