I need get all photo albums from device. I use this code for fetch albums:
func fetchAlbums() {
// Get all user albums
let userAlbumsOptions = PHFetchOptions()
userAlbumsOptions.predicate = NSPredicate(format: "estimatedAssetCount > 0")
let userAlbums = PHAssetCollection.fetchAssetCollections(with: PHAssetCollectionType.album, subtype: PHAssetCollectionSubtype.any, options: userAlbumsOptions)
userAlbums.enumerateObjects( {
if let collection = $0.0 as? PHAssetCollection {
print("album title: \(collection.localizedTitle)")
let onlyImagesOptions = PHFetchOptions()
onlyImagesOptions.predicate = NSPredicate(format: "mediaType = %i", PHAssetMediaType.image.rawValue)
if let result = PHAsset.fetchKeyAssets(in: collection, options: onlyImagesOptions) {
print("Images count: \(result.count)")
if result.count > 0 {
//Add album titie
self.albumsTitles.append(collection.localizedTitle!)
//Add album
self.albumsArray.append(result as! PHFetchResult<AnyObject>)
}
}
}
} )
}
But i can't get all photos. All albums without photos from iCloud library, only local photos.
I use Collection View for preview photo. Example my code for fetch photos from selected album:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: AlbumPhotoCollectionViewCell.self),
for: indexPath as IndexPath) as! AlbumPhotoCollectionViewCell
//Array with albums
let asset = self.albumsArray[indexSelectedAlbum]
let album = asset[indexPath.item]
let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = true
PHImageManager.default().requestImage(for: album as! PHAsset ,
targetSize: self.assetThumbnailSize,
contentMode: .aspectFill,
options: options,
resultHandler: {(result, info)in
if result != nil {
cell.albumPhoto.image = result
}
})
return cell
}
I change fetch and all working.
Old code:
if let result = PHAsset.fetchKeyAssets(in: collection, options: onlyImagesOptions){
//Code
}
New code
let result = PHAsset.fetchAssets(in: collection, options: onlyImagesOptions)
Related
I am trying to display a collection view of photo albums on the device. I am able to get the title but not sure how to get the Albums photo and set to the cell.
This is what I have:
import UIKit
import Photos
class PhotoAlbumViewController: UICollectionViewController {
var albumList: PHFetchResult<PHAssetCollection>! = nil
override func viewDidLoad() {
super.viewDidLoad()
albumList = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumRegular, options: nil)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
albumList.count
}
override func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
let album = albumList.object(at: indexPath.row)
if let label = cell.viewWithTag(4000) as? UILabel {
label.text = album.localizedTitle
}
}
}
I have a UI Label in my storyboard and label.text = album.localizedTitle sets the Album title correctly. Not sure how to get the image and set it to my Image component.
You can try this to get all ALBUM names from Photo Library
func get_All_Albums()
{
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 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")
}
}
}
}
}
}
& 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))
}
})
}
}
}
}
}
}
}
}
I am using below code for getting videos(URL, Durations, Thumbnails). After Fetching data i am displaying it on CollectionView.
The main problem is that, some video and its thumbnails not match each other. Can any one please tell me how i can fix it, or any other better solution?
Thanks
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
cell.imgV.image = photoLibrary[indexPath.row]
let duration: TimeInterval = videosDuration[indexPath.row] // 2 minutes, 30 seconds
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.allowedUnits = [ .minute, .second ]
formatter.zeroFormattingBehavior = [ .pad ]
let formattedDuration = formatter.string(from: duration)
cell.duration.text = "\(String(describing: formattedDuration!))"
return cell
}
func grabPhotos(){
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = false
requestOptions.deliveryMode = .highQualityFormat
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions) {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count{
//Used for fetch Image//
imgManager.requestImage(for: fetchResult.object(at: i) as PHAsset , targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image, error in
let imageOfVideo = image! as UIImage
self.photoLibrary.append(imageOfVideo)
})
//Used for fetch Video//
imgManager.requestAVAsset(forVideo: fetchResult.object(at: i) as PHAsset, options: PHVideoRequestOptions(), resultHandler: {(avAsset, audioMix, info) -> Void in
if let asset = avAsset as? AVURLAsset {
self.videoURL.append(asset.url)
let duration : CMTime = asset.duration
let durationInSecond = CMTimeGetSeconds(duration)
self.videosDuration.append(durationInSecond)
}
})
}
}
else{
//showAllertToImportImage()//A function to show alert
}
}
}
Since photos are being fetched asynchronously so the order is not maintained in the images and videos array, so to get the corresponding image for the video you can use dictionaries to store the result
I have made some modifications in your code, please check
var imageDictionary = [String: AnyObject]()
var videoDictionary = [String: AnyObject]()
func fetchData(){
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = false
requestOptions.deliveryMode = .highQualityFormat
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions) {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count{
//Used for fetch Image//
imgManager.requestImage(for: fetchResult.object(at: i) as PHAsset , targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image, error in
let imageOfVideo = image! as UIImage
//self.photoLibrary.append(imageOfVideo)
let key = "\(i)"
self.imageDictionary[key] = imageOfVideo
})
//Used for fetch Video//
imgManager.requestAVAsset(forVideo: fetchResult.object(at: i) as PHAsset, options: PHVideoRequestOptions(), resultHandler: {(avAsset, audioMix, info) -> Void in
if let asset = avAsset as? AVURLAsset {
//let videoData = NSData(contentsOf: asset.url)
self.videoURL.append(asset.url)
//print(asset.url)
let duration : CMTime = asset.duration
let durationInSecond = CMTimeGetSeconds(duration)
//self.videosDuration.append(durationInSecond)
//print(durationInSecond)
let key = "\(i)"
self.videoDictionary[key] = ["VideoURL" : asset.url, "VideoDuration" : durationInSecond]
}
})
}
}
else{
//showAllertToImportImage()//A function to show alert
}
}
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.imageDictionary.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//You can access the values like this....
let key = "\(indexPath.row)"
cell.image = self.imageDictionary[key] as? UIImage
let singleVideo = self.videoDictionary[key] as? [String: AnyObject]
cell.videoURL = singleVideo["VideoURL"] as? URL
cell.videoDuration = singleVideo["VideoDuration"] as? CMTime
}
Is there a way to add everything from your camera roll to an array?
import Photos
class MyVC: UIViewController
{
var images:NSMutableArray! // Array for storing images
func fetchPhotos () {
images = NSMutableArray()
self.fetchPhotoAtIndexFromEnd(0)
}
func getImageAtIndex(index:Int) {
let imgManager = PHImageManager.defaultManager()
var requestOptions = PHImageRequestOptions()
requestOptions.synchronous = true // if just return thumbnail not img
// optionally sort the images by creation date
var fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: false)]
if let fetchResult: PHFetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) {
if fetchResult.count > 0 {
imgManager.requestImageForAsset(fetchResult.objectAtIndex(fetchResult.count - 1 - index) as PHAsset, targetSize: view.frame.size, contentMode: PHImageContentMode.AspectFill, options: requestOptions, resultHandler: { (image, _) in
// Add img to images array
self.images.addObject(image)
if index + 1 < fetchResult.count {
self.fetchPhotoAtIndexFromEnd(index + 1)
} else {
println("Completed array: \(self.images)")
}
})
}
}
}
The app can create a custom album in the standard iOS photos application, but I have been unable to find a way for the app to gather all the images from that album to be displayed within the app.
Currently, the app is able to gather images from all the albums, just not one is particular.
let resultCollections = PHAssetCollection.fetchAssetCollectionsWithType(
.Album,
subtype: .AlbumRegular,
options: nil)
resultCollections.enumerateObjectsUsingBlock({
(object, index, stop) -> Void in
let collection = object as! PHAssetCollection
let result = PHAsset.fetchAssetsInAssetCollection(collection, options: nil)
result.enumerateObjectsUsingBlock({
(object, index, stop) -> Void in
let asset = object as! PHAsset
self.images.append(asset)
})
})
I have seen other questions that might be marked as duplicates, however the majority of them are talking about opening a UIPickerView to a custom album. This is a possible duplicate of How to fetch all images from custom Photo Album - swift however, it was never answered.
So, how can an iOS app gather all images from a particular photos album?
Add fetchOptions like below
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", YourAlbumTitle)
let resultCollections = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .AlbumRegular, options: fetchOptions)
Actually, the album title isn't a unique value, they can be duplicated. so I recommend using localIdentifier like below if your app access multiple albums.
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "localIdentifier = %#", YourAlbumLocalIdentifier)
let resultCollections = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .AlbumRegular, options: fetchOptions)
Working Code For Swift 4
My Answer might help you and others(https://stackoverflow.com/a/35178022/4795651) but then also adding the code here..!!
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)
}
class AlbumModel {
let name:String
let count:Int
let asset:NSMutableArray
init(name:String, count:Int, asset:NSMutableArray) {
self.name = name
self.count = count
self.asset = asset
}
}
class yourCustomCell: UITableViewCell {
//MARK:- Properties
#IBOutlet weak var collectionView: UICollectionView!
//MARK:- initialization methods
override func awakeFromNib() {
super.awakeFromNib()
// setupView()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
//MARK:- Setup collectionView datasource and delegate
func setCollectionViewDataSourceDelegate<T:UICollectionViewDataSource & UICollectionViewDelegate>(dataSourceDelegate: T, forRow row: Int) {
collectionView.delegate = dataSourceDelegate
collectionView.dataSource = dataSourceDelegate
collectionView.tag = row
collectionView.reloadData()
}
}
class ViewController: UIViewController {
var tablearray = NSMutableArray()
func getAssetThumbnail(asset: PHAsset) -> UIImage {
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
manager.requestImage(for: asset, targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
thumbnail = result!
})
return thumbnail
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//print(UnladenSwallow.unknown)
let fetchOptions = PHFetchOptions()
let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: fetchOptions)
let topLevelfetchOptions = PHFetchOptions()
let topLevelUserCollections = PHCollectionList.fetchTopLevelUserCollections(with: topLevelfetchOptions)
let allAlbums = [topLevelUserCollections, smartAlbums]
var name = ""
smartAlbums.enumerateObjects({
if let collection = $0.0 as? PHAssetCollection{
name = collection.localizedTitle!
let image_arry = NSMutableArray()
let result = PHAsset.fetchAssets(in: collection, options: nil)
result.enumerateObjects({ (object, index, stop) -> Void in
let asset = object
image_arry.add(self.getAssetThumbnail(asset: asset))
})
let newAlbum = AlbumModel(name: name, count: collection.estimatedAssetCount, asset:image_arry)
self.tablearray.add(newAlbum)
}
})
topLevelUserCollections.enumerateObjects({
if let collection = $0.0 as? PHAssetCollection{
name = collection.localizedTitle!
let image_arry = NSMutableArray()
let result = PHAsset.fetchAssets(in: collection, options: nil)
result.enumerateObjects({ (object, index, stop) -> Void in
let asset = object
image_arry.add(self.getAssetThumbnail(asset: asset))
})
let newAlbum = AlbumModel(name: name, count: collection.estimatedAssetCount, asset:image_arry)
self.tablearray.add(newAlbum)
}
})
print(self.tablearray)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDataSource,UITableViewDelegate{
func numberOfSections(in tableView: UITableView) -> Int{
return self.tablearray.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let album = self.tablearray[section] as! AlbumModel
return album.name
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! yourCustomCell
cell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.section)
return cell
}
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let album = self.tablearray[collectionView.tag] as! AlbumModel
print("count = \(album.asset.count)")
return album.asset.count;
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let album = self.tablearray[collectionView.tag] as! AlbumModel
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "col", for: indexPath)
let img = cell.viewWithTag(111) as! UIImageView
img.image = album.asset.object(at: indexPath.row) as? UIImage
return cell
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: IndexPath) {
print("get selected collectionview itemindex \(indexPath.row)")
}
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")
})
}
}
}