I have created an album programmatically. I want to check if image already exists in album before adding new image.
you can check with below code
CustomAlbum.shared.saveImage(image: UIImage())
save image like this.
import Foundation
import Photos
class CustomAlbum {
static let albumName = "xyz"
static let shared = CustomAlbum()
var assetCollection: PHAssetCollection!
init() {
func fetchAssetCollectionForAlbum() -> PHAssetCollection! {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", CustomAlbum.albumName)
let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let _: AnyObject = collection.firstObject {
return collection.firstObject!
}
return nil
}
if let assetCollection = fetchAssetCollectionForAlbum() {
self.assetCollection = assetCollection
return
}
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: CustomAlbum.albumName)
}) { _, _ in
self.assetCollection = fetchAssetCollectionForAlbum()
}
}
func saveImage(image: UIImage) {
if assetCollection == nil { return }
PHPhotoLibrary.shared().performChanges({
let assetPlaceholder = PHAssetChangeRequest.creationRequestForAsset(from: image).placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
let assetEnumeration: NSArray = [assetPlaceholder!]
albumChangeRequest?.addAssets(assetEnumeration)
}, completionHandler: nil)
}
func allPhotos(albumName: String = "xyz", albumImages: #escaping ([UIImage]) -> Void) {
let group = DispatchGroup()
var images: [Image] = []
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", albumName)
let resultCollections = PHAssetCollection.fetchAssetCollections(
with: .album,
subtype: .albumRegular,
options: fetchOptions)
resultCollections.enumerateObjects({
(object, index, stop) -> Void in
let collection = object
let result = PHAsset.fetchAssets(in: collection, options: nil)
result.enumerateObjects({
(object, index, stop) -> Void in
group.enter()
images.append(object.getfullImage())
group.leave()
})
})
group.notify(queue: DispatchQueue.main) {
albumImages(images)
}
}
}
with this code i'm fetching all images of album and comparing against the image I want to save.
PHPhotoLibrary.shared().allPhotos { (images) in
let image = UIImage()
}
class func getPhotofolder() -> String{
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("hsafetyPhoto") //hsafetyPhoto is my folder name to store the image and if doesnt exist then system will create one
if !fileManager.fileExists(atPath: paths){
try! fileManager.createDirectory(atPath: paths, withIntermediateDirectories: true, attributes: nil)
}else{
print("Already dictionary created.")
}
return paths
}
//Save Image At hsafetyPhoto Document Directory
class func saveImageDocumentDirectory(photo : UIImage, photoUrl : String) -> Bool{
let fileManager = FileManager.default
let paths = Utility.getPhotofolder().stringByAppendingPathComponent(pathComponent: photoUrl)
print("image's path \(paths)")
if !fileManager.fileExists(atPath: paths){
let imageData = UIImageJPEGRepresentation(photo, 0.5)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
if !fileManager.fileExists(atPath: paths){
return false
}else{
return true
}
}else{
print(paths)
let imageData = UIImageJPEGRepresentation(photo, 0.5)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
if !fileManager.fileExists(atPath: paths){
return false
}else{
return true
}
}
}
Related
I am working on an iOS Swift 5 project and want to download image from my Project App to a folder in gallery. Folder name would be same as my App name and if doesn't exist in gallery, then code should first create App folder in gallery then save image to it.
Need help to resolve this.
as i implemented a year ago
got code from stackoverflow
import Photos
class PhotoManager {
static let instance = PhotoManager()
var folder: PHCollectionList?
/// Fetches an existing folder with the specified identifier or creates one with the specified name
func fetchFolderWithIdentifier(_ identifier: String, name: String) {
let fetchResult = PHCollectionList.fetchCollectionLists(withLocalIdentifiers: [identifier], options: nil)
guard let folder = fetchResult.firstObject else {
createFolderWithName(name)
return
}
self.folder = folder
}
/// Creates a folder with the specified name
private func createFolderWithName(_ name: String) {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let changeRequest = PHCollectionListChangeRequest.creationRequestForCollectionList(withTitle: name)
placeholder = changeRequest.placeholderForCreatedCollectionList
}) { (success, error) in
guard let placeholder = placeholder else { return }
let fetchResult = PHCollectionList.fetchCollectionLists(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
guard let folder = fetchResult.firstObject else { return }
self.folder = folder
}
}
/// Creates an album with the specified name
private func createAlbumWithName(_ name: String, completion: #escaping (PHAssetCollection?) -> Void) {
guard let folder = folder else {
completion(nil)
return
}
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let listRequest = PHCollectionListChangeRequest(for: folder)
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: name)
listRequest?.addChildCollections([createAlbumRequest.placeholderForCreatedAssetCollection] as NSArray)
placeholder = createAlbumRequest.placeholderForCreatedAssetCollection
}) { (success, error) in
guard let placeholder = placeholder else {
completion(nil)
return
}
let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
let album = fetchResult.firstObject
completion(album)
}
}
/// Saves the image to a new album with the specified name
func saveImageToAlbumInRootFolder(_ albumName: String, image: UIImage?, completion: #escaping (Error?) -> Void) {
createAlbumWithName(albumName) { (album) in
guard let album = album else {
return
}
PHPhotoLibrary.shared().performChanges({
let albumChangeRequest = PHAssetCollectionChangeRequest(for: album)
let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image!)
let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset!
albumChangeRequest?.addAssets([photoPlaceholder] as NSArray)
}, completionHandler: { (success, error) in
if success {
completion(nil)
} else if let error = error {
// Failed with error
} else {
// Failed with no error
}
})
}
}}
currently i am working on a project in office that's why i am not providing you the exact solution but you can figure it out easily from the above class ...
you can use it PhotoManager.instance.saveImageToAlbumInRootFolder(_ albumName: String, image: yourImage) {completion}
import Foundation
import Photos
class CustomPhotoAlbum: NSObject {
static let albumName = "Your App Name"
static let sharedInstance = CustomPhotoAlbum()
var assetCollection: PHAssetCollection!
override init() {
super.init()
if let assetCollection = fetchAssetCollectionForAlbum() {
self.assetCollection = assetCollection
return
}
if PHPhotoLibrary.authorizationStatus() != PHAuthorizationStatus.authorized {
PHPhotoLibrary.requestAuthorization({ (status: PHAuthorizationStatus) -> Void in
()
})
}
if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized {
self.createAlbum()
} else {
PHPhotoLibrary.requestAuthorization(requestAuthorizationHandler)
}
}
func requestAuthorizationHandler(status: PHAuthorizationStatus) {
if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized {
// ideally this ensures the creation of the photo album even if authorization wasn't prompted till after init was done
print("trying again to create the album")
self.createAlbum()
} else {
print("should really prompt the user to let them know it's failed")
}
}
func createAlbum() {
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: CustomPhotoAlbum.albumName) // create an asset collection with the album name
}) { success, error in
if success {
self.assetCollection = self.fetchAssetCollectionForAlbum()
} else {
print("error \(error)")
}
}
}
func fetchAssetCollectionForAlbum() -> PHAssetCollection? {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", CustomPhotoAlbum.albumName)
let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let _: AnyObject = collection.firstObject {
return collection.firstObject
}
return nil
}
func save(image: UIImage) {
if assetCollection == nil {
return // if there was an error upstream, skip the save
}
PHPhotoLibrary.shared().performChanges({
let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceHolder = assetChangeRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
let enumeration: NSArray = [assetPlaceHolder!]
albumChangeRequest!.addAssets(enumeration)
}, completionHandler: nil)
}
}
how to use it
func haiJeenyKaMaqsadAuronKKamAna() {
CustomPhotoAlbum.sharedInstance.createAlbum()
CustomPhotoAlbum.sharedInstance.save(image: UIImage(named: "help")!)
}
now this is working fine as i copied it from my old project
I am trying to save generated UIImage to Camera Roll.
I have necessary privacy string in Info.plist.
I tried couple of methods;
The error I am facing for PHPhotoLibrary is
Error Domain=com.apple.accounts Code=7 "(null)
The codes I have tried;
UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil);
The other one is;
PHPhotoLibrary.shared().savePhoto(image: image!, albumName: "AlbumName", completion: { (asset) in
if asset != nil
{
print("error")
}
})
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)
}
})
}
Could you please help me on figuring out this?
BR,
Erdem
I have figured it out.
The problem is I have been creating QR Image that is created with CIFilter is CIImage.
It returns error code = -1
You need to create UIImage from CGImage not CIImage
if let output = filter.outputImage?.transformed(by: transform) {
let context = CIContext()
guard let cgImage = context.createCGImage(output, from: output.extent) else { return nil }
return UIImage(cgImage: cgImage)
}
I am storing the photo with the use of following code. But now I have to get the photos from storage using name.
First Question: How can I store the photos using name ? Should I store it in Core Data ?
Second Question: How can I get that photo using the name I have given it previously ?
Please Help me. Thank you for all replies ...
class CustomPhotoAlbum: NSObject {
static let albumName = "PhotoAlbumName"
static let sharedInstance = CustomPhotoAlbum()
var assetCollection: PHAssetCollection!
override init() {
super.init()
if let assetCollection = fetchAssetCollectionForAlbum() {
self.assetCollection = assetCollection
return
}
if PHPhotoLibrary.authorizationStatus() != PHAuthorizationStatus.authorized {
PHPhotoLibrary.requestAuthorization({ (status: PHAuthorizationStatus) -> Void in
()
})
}
if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized {
self.createAlbum()
} else {
PHPhotoLibrary.requestAuthorization(requestAuthorizationHandler)
}
}
func requestAuthorizationHandler(status: PHAuthorizationStatus) {
if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized {
// ideally this ensures the creation of the photo album even if authorization wasn't prompted till after init was done
print("trying again to create the album")
self.createAlbum()
} else {
print("should really prompt the user to let them know it's failed")
}
}
func createAlbum() {
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: CustomPhotoAlbum.albumName) // create an asset collection with the album name
}) { success, error in
if success {
self.assetCollection = self.fetchAssetCollectionForAlbum()
} else {
print("error \(String(describing: error))")
}
}
}
func fetchAssetCollectionForAlbum() -> PHAssetCollection? {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", CustomPhotoAlbum.albumName)
let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let _: AnyObject = collection.firstObject {
return collection.firstObject
}
return nil
}
func save(image: UIImage) {
if assetCollection == nil {
return // if there was an error upstream, skip the save
}
PHPhotoLibrary.shared().performChanges({
let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceHolder = assetChangeRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
let enumeration: NSArray = [assetPlaceHolder!]
albumChangeRequest!.addAssets(enumeration)
}, completionHandler: nil)
}
}
You can use this class .
import Foundation
import Photos
class FetchPhotos{
var images:[UIImage] = []
var imageUrl:String!
func fetchPhotos() -> String{
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: false)]
// Fetch the image assets
let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
// If the fetch result isn't empty,
// proceed with the image request
if fetchResult.count > 0 {
let totalImageCountNeeded = 1 // <-- The number of images to fetch
fetchPhotoAtIndex(0, totalImageCountNeeded, fetchResult)
}
return imageUrl
}
// Repeatedly call the following method while incrementing
// the index until all the photos are fetched
func fetchPhotoAtIndex(_ index:Int, _ totalImageCountNeeded: Int, _ fetchResult: PHFetchResult<PHAsset>) {
let albumName = "CustonAlbum"
// Note that if the request is not set to synchronous
// the requestImageForAsset will return both the image
// and thumbnail; by setting synchronous to true it
// will return just the thumbnail
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
let collection: PHFetchResult =
PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil)
for k in 0 ..< collection.count {
let obj:AnyObject! = collection.object(at: k)
if obj.title == albumName {
print("Yeap!")
// Perform the image request
PHImageManager.default().requestImage(for: fetchResult.object(at: index) as PHAsset, targetSize: CGSize(width: 1000, height: 1000), contentMode: PHImageContentMode.aspectFill, options: requestOptions, resultHandler: { (image, info) in
if let image = image {
// Add the returned image to your array
self.images += [image]
}
// If you haven't already reached the first
// index of the fetch result and if you haven't
// already stored all of the images you need,
// perform the fetch request again with an
// incremented index
if index + 1 < fetchResult.count && self.images.count < totalImageCountNeeded {
self.fetchPhotoAtIndex(index + 1, totalImageCountNeeded, fetchResult)
} else {
// Else you have completed creating your array
print("Completed array: \(self.images[0])")
print("Image URL \(String(describing: info!["PHImageFileURLKey"]))")
self.imageUrl = "\(info!["PHImageFileURLKey"]!)"
}
})
}}
}
}
I have a custom album in which my app saves picture from camera. I am wondering if there is a way I can create folders inside my album so I can stack certain images inside it?
ANSWER
As fellow members mentioned, sadly there is no way you can create a folder inside album.
You should try code below. It's Swift 3.0 syntaxe. :)
import Foundation
import Photos
class CustomPhotoAlbum: NSObject {
static let albumName = "Album Name"
static let sharedInstance = CustomPhotoAlbum()
var assetCollection: PHAssetCollection!
override init() {
super.init()
if let assetCollection = fetchAssetCollectionForAlbum() {
self.assetCollection = assetCollection
return
}
if PHPhotoLibrary.authorizationStatus() != PHAuthorizationStatus.authorized {
PHPhotoLibrary.requestAuthorization({ (status: PHAuthorizationStatus) -> Void in
()
})
}
if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized {
self.createAlbum()
} else {
PHPhotoLibrary.requestAuthorization(requestAuthorizationHandler)
}
}
func requestAuthorizationHandler(status: PHAuthorizationStatus) {
if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized {
// ideally this ensures the creation of the photo album even if authorization wasn't prompted till after init was done
print("trying again to create the album")
self.createAlbum()
} else {
print("should really prompt the user to let them know it's failed")
}
}
func createAlbum() {
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: CustomPhotoAlbum.albumName) // create an asset collection with the album name
}) { success, error in
if success {
self.assetCollection = self.fetchAssetCollectionForAlbum()
} else {
print("error \(error)")
}
}
}
func fetchAssetCollectionForAlbum() -> PHAssetCollection? {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", CustomPhotoAlbum.albumName)
let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let _: AnyObject = collection.firstObject {
return collection.firstObject
}
return nil
}
func save(image: UIImage) {
if assetCollection == nil {
return // if there was an error upstream, skip the save
}
PHPhotoLibrary.shared().performChanges({
let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceHolder = assetChangeRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
let enumeration: NSArray = [assetPlaceHolder!]
albumChangeRequest!.addAssets(enumeration)
}, completionHandler: nil)
}
}
You can add albums within folders in the user's Photos Albums. I just figured out how to do it, today:
import Photos
class PhotoManager {
static let instance = PhotoManager()
var folder: PHCollectionList?
/// Fetches an existing folder with the specified identifier or creates one with the specified name
func fetchFolderWithIdentifier(_ identifier: String, name: String) {
let fetchResult = PHCollectionList.fetchCollectionLists(withLocalIdentifiers: [identifier], options: nil)
guard let folder = fetchResult.firstObject else {
createFolderWithName(name)
return
}
self.folder = folder
}
/// Creates a folder with the specified name
private func createFolderWithName(_ name: String) {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let changeRequest = PHCollectionListChangeRequest.creationRequestForCollectionList(withTitle: name)
placeholder = changeRequest.placeholderForCreatedCollectionList
}) { (success, error) in
guard let placeholder = placeholder else { return }
let fetchResult = PHCollectionList.fetchCollectionLists(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
guard let folder = fetchResult.firstObject else { return }
self.folder = folder
}
}
/// Creates an album with the specified name
private func createAlbumWithName(_ name: String, completion: #escaping (PHAssetCollection?) -> Void) {
guard let folder = folder else {
completion(nil)
return
}
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let listRequest = PHCollectionListChangeRequest(for: folder)
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: name)
listRequest?.addChildCollections([createAlbumRequest.placeholderForCreatedAssetCollection] as NSArray)
placeholder = createAlbumRequest.placeholderForCreatedAssetCollection
}) { (success, error) in
guard let placeholder = placeholder else {
completion(nil)
return
}
let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
let album = fetchResult.firstObject
completion(album)
}
}
/// Saves the image to a new album with the specified name
func saveImageToAlbumInRootFolder(_ albumName: String, image: UIImage?, completion: #escaping (Error?) -> Void) {
createAlbumWithName(albumName) { (album) in
guard let album = album else {
return
}
PHPhotoLibrary.shared().performChanges({
let albumChangeRequest = PHAssetCollectionChangeRequest(for: album)
let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image!)
let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset!
albumChangeRequest?.addAssets([photoPlaceholder] as NSArray)
}, completionHandler: { (success, error) in
if success {
completion(nil)
} else if let error = error {
// Failed with error
} else {
// Failed with no error
}
})
}
}
}
This allows you to do something like this:
let defaults = UserDefaults.standard
let identifier = defaults.string(forKey: "myFolder")!
PhotoManager.instance.fetchFolderWithIdentifier(identifier, name: "My Folder")
PhotoManager.instance.saveImageToAlbumInRootFolder("My Album", image: UIImage(named: "my_image")) { (error) in
// Handle error
}
How to fetch all images from custom Photo Album?
var fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: false)]
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Image.rawValue)
let allImages:PHFetchResult = PHAsset.fetchKeyAssetsInAssetCollection(albumList[index].collection, options: fetchOptions)
This code block is fetching just a few of them.
Thanks.
-> albumList[index].collection 's type is PHAssetCollection
For Swift 4
using this answer https://stackoverflow.com/a/28904792/4795651 edited a little for myself.
import Photos
func fetchCustomAlbumPhotos()
{
let albumName = "Album Name Here"
var assetCollection = PHAssetCollection()
var albumFound = Bool()
var photoAssets = PHFetchResult<AnyObject>()
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", albumName)
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let firstObject = collection.firstObject{
//found the album
assetCollection = firstObject
albumFound = true
}
else { albumFound = false }
_ = collection.count
photoAssets = PHAsset.fetchAssets(in: assetCollection, options: nil) as! PHFetchResult<AnyObject>
let imageManager = PHCachingImageManager()
photoAssets.enumerateObjects{(object: AnyObject!,
count: Int,
stop: UnsafeMutablePointer<ObjCBool>) in
if object is PHAsset{
let asset = object as! PHAsset
print("Inside If object is PHAsset, This is number 1")
let imageSize = CGSize(width: asset.pixelWidth,
height: asset.pixelHeight)
/* For faster performance, and maybe degraded image */
let options = PHImageRequestOptions()
options.deliveryMode = .fastFormat
options.isSynchronous = true
imageManager.requestImage(for: asset,
targetSize: imageSize,
contentMode: .aspectFill,
options: options,
resultHandler: {
(image, info) -> Void in
self.photo = image!
/* The image is now available to us */
self.addImgToArray(uploadImage: self.photo!)
print("enum for image, This is number 2")
})
}
}
}
func addImgToArray(uploadImage:UIImage)
{
self.images.append(uploadImage)
}
For Swift 2.1
import Photos
func FetchCustomAlbumPhotos()
{
var albumName = "SwiftAlbum"
var assetCollection = PHAssetCollection()
var albumFound = Bool()
var photoAssets = PHFetchResult()
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", albumName)
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions)
if let first_Obj:AnyObject = collection.firstObject{
//found the album
assetCollection = collection.firstObject as! PHAssetCollection
albumFound = true
}
else { albumFound = false }
var i = collection.count
photoAssets = PHAsset.fetchAssetsInAssetCollection(assetCollection, options: nil)
let imageManager = PHCachingImageManager()
// let imageManager = PHImageManager.defaultManager()
photoAssets.enumerateObjectsUsingBlock{(object: AnyObject!,
count: Int,
stop: UnsafeMutablePointer<ObjCBool>) in
if object is PHAsset{
let asset = object as! PHAsset
print("Inside If object is PHAsset, This is number 1")
let imageSize = CGSize(width: asset.pixelWidth,
height: asset.pixelHeight)
/* For faster performance, and maybe degraded image */
let options = PHImageRequestOptions()
options.deliveryMode = .FastFormat
options.synchronous = true
imageManager.requestImageForAsset(asset,
targetSize: imageSize,
contentMode: .AspectFill,
options: options,
resultHandler: {
(image, info) -> Void in
self.photo = image!
/* The image is now available to us */
self.addImgToArray(self.photo)
print("enum for image, This is number 2")
})
}
}
}
func addImgToArray(uploadImage:UIImage)
{
self.images.append(uploadImage)
}
This is a custom album, so what you've got to do is to add it to your code in the middle:
import Photos
class CustomPhotoAlbum {
static let albumName = "Album"
static let sharedInstance = CustomPhotoAlbum()
var assetCollection: PHAssetCollection!
init() {
func fetchAssetCollectionForAlbum() -> PHAssetCollection! {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", CustomPhotoAlbum.albumName)
let collection = PHAssetCollection.fetchAssetCollections(with: .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.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: 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.shared().performChanges({
let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceholder = assetChangeRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
albumChangeRequest?.addAssets([assetPlaceholder] as NSFastEnumeration)
}, completionHandler: nil)
}
}
Then to fetch all the pics in your album use this code:
func getAlbum(title: String, completionHandler: #escaping (PHAssetCollection?) -> ()) {
DispatchQueue.global(qos: .background).async { [weak self] in
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", title)
let collections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let album = collections.firstObject {
completionHandler(album)
} else {
self?.createAlbum(withTitle: title, completionHandler: { (album) in
completionHandler(album)
})
}
}
}
To call this function use this example:
getAlbum(title: "Album") { [weak self] assetCollection in
guard let this = self else { return }
guard assetCollection != nil else { return }
print(assetCollection!)
}
If you want to create a custom album use this function:
func createAlbum(withTitle title: String, completionHandler: #escaping (PHAssetCollection?) -> ()) {
DispatchQueue.global(qos: .background).async {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: title)
placeholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { (created, error) in
var album: PHAssetCollection?
if created {
let collectionFetchResult = placeholder.map { PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [$0.localIdentifier], options: nil) }
album = collectionFetchResult?.firstObject
}
completionHandler(album)
})
}
}
This function will be called in the getAlbum, if the album isn't created.
Try this to get Photos from a specific Album
func get_Photos_From_Album(albumName: String)
{
var photoLibraryImages = [UIImage]()
var photoLibraryAssets = [PHAsset]()
//whatever you need, you can use UIImage or PHAsset to photos in UICollectionView
DispatchQueue.global(qos: .userInteractive).async
{
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: nil)
let customAlbums = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil)
[smartAlbums, customAlbums].forEach {
$0.enumerateObjects { collection, index, stop in
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat
let photoInAlbum = PHAsset.fetchAssets(in: collection, options: fetchOptions)
if let title = collection.localizedTitle
{
if photoInAlbum.count > 0
{
print("\n\n \(title) --- count = \(photoInAlbum.count) \n\n")
}
if title == albumName
{
if photoInAlbum.count > 0
{
for i in (0..<photoInAlbum.count).reversed()
{
imgManager.requestImage(for: photoInAlbum.object(at: i) as PHAsset , targetSize: CGSize(width: 150, height: 150), contentMode: .aspectFit, options: requestOptions, resultHandler: {
image, error in
if image != nil
{
photoLibraryImages.append(image!)
photoLibraryAssets.append(photoInAlbum.object(at: i))
}
})
}
}
}
}
}
}
}
}
SWIFT 4
func FetchCustomAlbumPhotos()
{
let albumName = "AlbumName"
var assetCollection = PHAssetCollection()
var albumFound = Bool()
var photoAssets = PHFetchResult<AnyObject>()
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", albumName)
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let _:AnyObject = collection.firstObject{
//found the album
assetCollection = collection.firstObject!
albumFound = true
}
else { albumFound = false }
_ = collection.count
photoAssets = PHAsset.fetchAssets(in: assetCollection, options: nil) as! PHFetchResult<AnyObject>
let imageManager = PHCachingImageManager()
// let imageManager = PHImageManager.defaultManager()
photoAssets.enumerateObjects{(object: AnyObject!,
count: Int,
stop: UnsafeMutablePointer<ObjCBool>) in
if object is PHAsset{
let asset = object as! PHAsset
print("Inside If object is PHAsset, This is number 1")
let imageSize = CGSize(width: asset.pixelWidth,
height: asset.pixelHeight)
/* For faster performance, and maybe degraded image */
let options = PHImageRequestOptions()
options.deliveryMode = .fastFormat
options.isSynchronous = true
imageManager.requestImage(for: asset,
targetSize: imageSize,
contentMode: .aspectFit ,
options: options,
resultHandler: {
(image, info) -> Void in
print("Image \(String(describing: image))")
//self.photo = image!
/* The image is now available to us */
//self.addImgToArray(self.photo)
print("enum for image, This is number 2")
})
}
}
}