objective c - fotos - ¿Cómo recuperar la foto más reciente de Camera Roll en iOS?
recuperar fotos iphone 2018 (7)
Me resulta difícil descubrir cómo recuperar mediante programación la foto más reciente en el rollo de la cámara sin la intervención del usuario. Para que quede claro, no quiero usar un Selector de imágenes, quiero que la aplicación tome automáticamente la foto más nueva cuando se abra.
Sé que esto es posible porque he visto a una aplicación similar hacerlo, pero parece que no puedo encontrar ninguna información al respecto.
En iOS 8, Apple agregó la biblioteca de fotos, que facilita las consultas. En iOS 9, ALAssetLibrary
está en deprecated .
Aquí hay un código Swift para obtener 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)
})
}
}
}
}
En lugar de jugar con el índice, puede enumerar a través de la lista al revés. Este patrón funciona bien si desea la imagen más reciente o si desea listar las imágenes en una vista UICollectionView con la imagen más reciente primero.
Ejemplo para devolver la imagen 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;
}
}];
Para agregar a la respuesta de Art Gillespie, el uso de fullResolutionImage
usa la imagen original que, dependiendo de la orientación del dispositivo al tomar la foto, podría dejar una imagen al revés o -90 °.
Para obtener la imagen modificada, pero optimizada para esto, use fullScreenImage
en fullScreenImage
lugar ...
UIImage *img = [UIImage imageWithCGImage:[repr fullScreenImage]];
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 occurred: /(error.localizedDescription)")
}
}
Swift 3.0:
1) Importar marco de fotos en su encabezado antes de su declaración de clase.
import Photos
2) Agregue el siguiente método, que devuelve la última imagen.
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 botón):
@IBAction func pressedLastPictureAttachmentButton(_ sender: Any) {
queryLastPhoto(resizeTo: nil){
image in
print(image)
}
}
Una forma es usar AssetsLibrary y usar n - 1 como el í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);
}];
Uso de la biblioteca de fotos (Objective-C)
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:fetchOptions];
if (assetsFetchResult.count>0) {
PHAsset *asset = [assetsFetchResult objectAtIndex:0];
CGFloat scale = [UIScreen mainScreen].scale;
CGFloat dimension = 55.0f; // set your required size
CGSize size = CGSizeMake(dimension*scale, dimension*scale);
[[PHImageManager defaultManager] requestImageForAsset:asset
targetSize:size
contentMode:PHImageContentModeAspectFit
options:nil
resultHandler:^(UIImage *result, NSDictionary *info) {
// do your thing with the image
}
];
}