¿Cómo recuperar la foto más reciente de Camera Roll en iOS?

Me está costando averiguar cómo recuperar mediante progtwigción la foto más reciente en el rollo de la camera sin la intervención del usuario. Para ser claro, no quiero usar un selector de image, quiero que la aplicación capture automáticamente la foto más nueva cuando se abra la aplicación.

Sé que esto es posible porque he visto una aplicación similar hacerlo, pero parece que no puedo encontrar ninguna información al respecto.

Una forma es usar AssetsLibrary y usar n – 1 como índice para la enumeración.

ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { if (nil != group) { // be sure to filter the group so you only get photos [group setAssetsFilter:[ALAssetsFilter allPhotos]]; if (group.numberOfAssets > 0) { [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:group.numberOfAssets - 1] options:0 usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { if (nil != result) { ALAssetRepresentation *repr = [result defaultRepresentation]; // this is the most recent saved photo UIImage *img = [UIImage imageWithCGImage:[repr fullResolutionImage]]; // we only need the first (most recent) photo -- stop the enumeration *stop = YES; } }]; } } *stop = NO; } failureBlock:^(NSError *error) { NSLog(@"error: %@", error); }]; 

En lugar de jugar con el índice, puede enumerar a través de la list en reversa. Este patrón funciona bien si desea la image más reciente o si desea enumerar las imágenes en una UICollectionView con la image más reciente primero.

Ejemplo para devolver la image más reciente:

 [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) { if (asset) { ALAssetRepresentation *repr = [asset defaultRepresentation]; UIImage *img = [UIImage imageWithCGImage:[repr fullResolutionImage]]; *stop = YES; } }]; 

En iOS 8, Apple agregó la biblioteca de fotos que facilita la consulta. En iOS 9, ALAssetLibrary está en desuso .

Aquí hay un código Swift para get la foto más reciente tomada con ese marco.

 import UIKit import Photos struct LastPhotoRetriever { func queryLastPhoto(resizeTo size: CGSize?, queryCallback: (UIImage? -> Void)) { let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] // fetchOptions.fetchLimit = 1 // This is available in iOS 9. if let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) { if let asset = fetchResult.firstObject as? PHAsset { let manager = PHImageManager.defaultManager() // If you already know how you want to resize, // great, otherwise, use full-size. let targetSize = size == nil ? CGSize(width: asset.pixelWidth, height: asset.pixelHeight) : size! // I arbitrarily chose AspectFit here. AspectFill is // also available. manager.requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFit, options: nil, resultHandler: { image, info in queryCallback(image) }) } } } } 

Para agregar a la respuesta de Art Gillespie, usar fullResolutionImage utiliza la image original que, dependiendo de la orientación del dispositivo al tomar la foto, podría dejarle una image invertida o de -90 °.

Para get la image modificada pero optimizada para esto, use fullScreenImage en fullScreenImage lugar …

  UIImage *img = [UIImage imageWithCGImage:[repr fullScreenImage]]; 

Swift 3.0:

1) Importar marco de fotos en su encabezado antes de su statement de class.

 import Photos 

2) Agregue el siguiente método, que devuelve la última image.

 func queryLastPhoto(resizeTo size: CGSize?, queryCallback: @escaping ((UIImage?) -> Void)) { let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] let requestOptions = PHImageRequestOptions() requestOptions.isSynchronous = true let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions) if let asset = fetchResult.firstObject { let manager = PHImageManager.default() let targetSize = size == nil ? CGSize(width: asset.pixelWidth, height: asset.pixelHeight) : size! manager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFit, options: requestOptions, resultHandler: { image, info in queryCallback(image) }) } } 

3) Luego, llame a este método en algún lugar de su aplicación (tal vez una acción de button):

 @IBAction func pressedLastPictureAttachmentButton(_ sender: Any) { queryLastPhoto(resizeTo: nil){ image in print(image) } } 

Respuesta a la pregunta (en Swift ):

  func pickingTheLastImageFromThePhotoLibrary() { let assetsLibrary: ALAssetsLibrary = ALAssetsLibrary() assetsLibrary.enumerateGroupsWithTypes(ALAssetsGroupSavedPhotos, usingBlock: { (let group: ALAssetsGroup!, var stop: UnsafeMutablePointer<ObjCBool>) -> Void in if (group != nil) { // Be sure to filter the group so you only get photos group.setAssetsFilter(ALAssetsFilter.allPhotos()) group.enumerateAssetsWithOptions(NSEnumerationOptions.Reverse, usingBlock: { (let asset: ALAsset!, let index: Int, var stop: UnsafeMutablePointer<ObjCBool>) -> Void in if(asset != nil) { /* Returns a CGImage representation of the asset. Using the fullResolutionImage uses the original image which — depending on the device's orientation when taking the photo — could leave you with an upside down, or -90° image. To get the modified, but optimised image for this, use fullScreenImage instead. */ // let myCGImage: CGImage! = asset.defaultRepresentation().fullResolutionImage().takeUnretainedValue() /* Returns a CGImage of the representation that is appropriate for displaying full screen. */ // let myCGImage: CGImage! = asset.defaultRepresentation().fullScreenImage().takeUnretainedValue() /* Returns a thumbnail representation of the asset. */ let myCGImage: CGImage! = asset.thumbnail().takeUnretainedValue() // Here we set the image included in the UIImageView self.myUIImageView.image = UIImage(CGImage: myCGImage) stop.memory = ObjCBool(true) } }) } stop.memory = ObjCBool(false) }) { (let error: NSError!) -> Void in println("A problem occurnetworking: \(error.localizedDescription)") } }