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)")
}
})
}
}
}
Related
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 am trying to fetch all the photos (PHAssets) in an album and appending them in an array so I can pass it as completion parameter.
The code is crashing at the line containing arrayOfPHAsset.append(asset). Why? What do I need to change in my code to make it work?
This is the code I am using.
func fetchCustomAlbumPhotos( completion : (_ array : [PHAsset]) -> Void)
{
var assetCollection = PHAssetCollection()
var albumFound = Bool()
var photoAssets = PHFetchResult<AnyObject>()
var arrayOfPHAsset : [PHAsset]!
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", CustomAlbum.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
completion([])
}
_ = 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(asset)
arrayOfPHAsset.append(asset)
// 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")
//
// })
}
})
print("arrayOfPHAsset : \(arrayOfPHAsset), arrayOfPHAsset count : \(arrayOfPHAsset.count)")
completion(arrayOfPHAsset)
}
The following line in the code you are showing is not allocating the array; it is just declaring it.
var arrayOfPHAsset : [PHAsset]!
You need to allocate the array too.
var arrayOfPHAsset : [PHAsset] = []
Then you can add items to the array.
arrayOfPHAsset.append(asset)
I have this function. This function initializes all the media files for gallery view.
func initMediaFiles() {
var assets: [PHAsset] = []
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
options.fetchLimit = 1000
let results = PHAsset.fetchAssets(with: .image, options: options)
results.enumerateObjects({ (object, _, _) in
if let asset = object as? PHAsset {
assets.append(asset)
}
})
SCPAsset.imageManager.startCachingImages(for: assets, targetSize: CGSize(width: 110.0, height: 147.0),contentMode: .aspectFill, options: nil)
for asset in assets {
let scpAsset = SCPAsset(initWithPHAsset: asset)
scpAsset.inspectionUUID = self.inspectionId!
self.mediaAssets.append(scpAsset)
}
}
I am not able to see why I am getting like 10,000 memory leak every time i load the gallery view.
Here's something I've done in a project that might help:
Some properties:
let requestOptions = PHImageRequestOptions()
let fetchOptions = PHFetchOptions()
let cachingImageManager = PHCachingImageManager()
var assets: [PHAsset] = [] {
willSet {
cachingImageManager.stopCachingImagesForAllAssets()
}
didSet {
cachingImageManager.startCachingImagesForAssets(assets,
targetSize: PHImageManagerMaximumSize,
contentMode: .AspectFit,
options: self.requestOptions
)
}
}
func fetchPhotos() {
requestOptions.resizeMode = PHImageRequestOptionsResizeMode.Exact
requestOptions.version = .Current
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat
requestOptions.synchronous = true
fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: false)]
if #available(iOS 9.0, *) {
fetchOptions.fetchLimit = 50
} else {
// Fallback on earlier versions
}
fetchResults = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions)
guard let fetchResults = fetchResults else {
print("No PHAssets")
return
}
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { [weak self] in
fetchResults.enumerateObjectsUsingBlock{ object, index, stop in
let asset = object as! PHAsset
self?.assets.append(asset)
}
dispatch_async(dispatch_get_main_queue()) {
self?.photoCollectionView.reloadData()
}
}
}
I have a collectionView running in my project that fetches iPhone photo library by using Photos framework successfully.I am trying to ascending the photo collectionView from last photo.I am using the following code....
func getAllPhotosInfo() {
photoAssets = []
let options = PHFetchOptions()
options.sortDescriptors = [
NSSortDescriptor(key: "creationDate", ascending: false)
]
let assets: PHFetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: options)
assets.enumerateObjectsUsingBlock { (asset, index, stop) -> Void in
self.photoAssets.append(asset as! PHAsset)
}
print(photoAssets)
}
//PHAsset to image conversion
import UIKit
import Photos
class CollectionViewCell: UICollectionViewCell {
var imageManager: PHImageManager?
#IBOutlet weak var photoImageView: UIImageView!
var imageAsset: PHAsset? {
didSet {
self.imageManager?.requestImageForAsset(self.imageAsset!, targetSize: CGSize(width: 320, height: 320), contentMode: .AspectFill, options: nil) { image, info in
self.photoImageView.image = image
}
}
}
}
I was playing with the Photos framework doc and I found the answer.here is the working code....
var photoAssets = [PHAsset]()
func getAllPhotosInfo() {
photoAssets = []
let options = PHFetchOptions()
options.sortDescriptors = [ NSSortDescriptor(key: "creationDate", ascending: false) ]
options.predicate = NSPredicate(format: "mediaType = %i", PHAssetMediaType.Image.rawValue)
let assetCollections = PHAssetCollection.fetchAssetCollectionsWithType(PHAssetCollectionType.SmartAlbum, subtype: PHAssetCollectionSubtype.SmartAlbumUserLibrary, options: nil)
for i in 0 ..< assetCollections.count
{
if let assetCollection = assetCollections[i] as? PHAssetCollection
{
images = PHAsset.fetchAssetsInAssetCollection(assetCollection, options: options)
print(images.count)
return
}
}
}
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")
})
}
}
}