Skip to content

Instantly share code, notes, and snippets.

@tiagobbraga
Forked from khorbushko/PHPhotoLibrary+SaveImage
Last active November 27, 2019 01:48
Show Gist options
  • Save tiagobbraga/bd90ff6545b8a321ab1fa8e82ff20710 to your computer and use it in GitHub Desktop.
Save tiagobbraga/bd90ff6545b8a321ab1fa8e82ff20710 to your computer and use it in GitHub Desktop.
PHPhotoLibrary+SaveImage - save image with Photos Framework swift 2.3 and 3
// SWIFT 3
import UIKit
import Photos
extension PHPhotoLibrary {
// MARK: - PHPhotoLibrary+SaveImage
// MARK: - Public
func savePhoto(image:UIImage, albumName:String, completion:((PHAsset?)->())? = nil) {
func save() {
if let album = PHPhotoLibrary.shared().findAlbum(albumName: albumName) {
PHPhotoLibrary.shared().saveImage(image: image, album: album, completion: completion)
} else {
PHPhotoLibrary.shared().createAlbum(albumName: albumName, completion: { (collection) in
if let collection = collection {
PHPhotoLibrary.shared().saveImage(image: image, album: collection, completion: completion)
} else {
completion?(nil)
}
})
}
}
if PHPhotoLibrary.authorizationStatus() == .authorized {
save()
} else {
PHPhotoLibrary.requestAuthorization({ (status) in
if status == .authorized {
save()
}
})
}
}
// MARK: - Private
fileprivate func findAlbum(albumName: String) -> PHAssetCollection? {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
let fetchResult : PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
guard let photoAlbum = fetchResult.firstObject else {
return nil
}
return photoAlbum
}
fileprivate func createAlbum(albumName: String, completion: @escaping (PHAssetCollection?)->()) {
var albumPlaceholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
albumPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { success, error in
if success {
guard let placeholder = albumPlaceholder else {
completion(nil)
return
}
let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
guard let album = fetchResult.firstObject else {
completion(nil)
return
}
completion(album)
} else {
completion(nil)
}
})
}
fileprivate func saveImage(image: UIImage, album: PHAssetCollection, completion:((PHAsset?)->())? = nil) {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album),
let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset else { return }
placeholder = photoPlaceholder
let fastEnumeration = NSArray(array: [photoPlaceholder] as [PHObjectPlaceholder])
albumChangeRequest.addAssets(fastEnumeration)
}, completionHandler: { success, error in
guard let placeholder = placeholder else {
completion?(nil)
return
}
if success {
let assets:PHFetchResult<PHAsset> = PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
let asset:PHAsset? = assets.firstObject
completion?(asset)
} else {
completion?(nil)
}
})
}
}
// SWIFT 2.3
import UIKit
import Photos
extension PHPhotoLibrary {
func savePhoto(image: UIImage, albumName: String, completion: ((PHAsset?)->())? = nil) {
func save() {
if let album = PHPhotoLibrary.sharedPhotoLibrary().findAlbum(albumName) {
PHPhotoLibrary.sharedPhotoLibrary().saveImage(image, album: album, completion: completion)
} else {
PHPhotoLibrary.sharedPhotoLibrary().createAlbum(albumName, completion: { (collection) in
if let collection = collection {
PHPhotoLibrary.sharedPhotoLibrary().saveImage(image, album: collection, completion: completion)
} else {
completion?(nil)
}
})
}
}
if PHPhotoLibrary.authorizationStatus() == .Authorized {
save()
} else {
PHPhotoLibrary.requestAuthorization({ (status) in
if status == .Authorized {
save()
}
})
}
}
private func findAlbum(albumName: String) -> PHAssetCollection? {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
let fetchResult: PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions)
guard let photoAlbum = fetchResult.firstObject else { return nil }
return photoAlbum as? PHAssetCollection
}
private func createAlbum(albumName: String, completion: (PHAssetCollection?)->()) {
var albumPlaceholder: PHObjectPlaceholder?
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle(albumName)
albumPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { (success, error) in
if success {
guard let placeholder = albumPlaceholder else {
completion(nil)
return
}
let fetchResult = PHAssetCollection.fetchAssetCollectionsWithLocalIdentifiers([placeholder.localIdentifier], options: nil)
guard let album = fetchResult.firstObject else {
completion(nil)
return
}
completion(album as? PHAssetCollection)
} else {
completion(nil)
}
})
}
private func saveImage(image: UIImage, album: PHAssetCollection, completion: ((PHAsset?)->())? = nil ) {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(image)
guard let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: album), let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset else { return }
placeholder = photoPlaceholder
let fastEnumeration = NSArray(array: [photoPlaceholder] as [PHObjectPlaceholder])
albumChangeRequest.addAssets(fastEnumeration)
}, completionHandler: { (success, error) in
guard let placeholder = placeholder else {
completion?(nil)
return
}
if success {
let assets: PHFetchResult = PHAsset.fetchAssetsWithLocalIdentifiers([placeholder.localIdentifier], options: nil)
let asset: PHAsset? = assets.firstObject as? PHAsset
completion?(asset)
} else {
completion?(nil)
}
})
}
}
@valterandremachado
Copy link

how do I call this extension inside of a different viewController?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment