lugares inc images imagenes fotos etiquetar apple actividades ios image camera photos

ios - inc - iphone photos



Obtener la Ășltima imagen de Photos.app? (13)

He visto otras aplicaciones hacerlo donde se puede importar la última foto de la aplicación de fotos para un uso rápido, pero hasta donde yo sé, solo sé cómo obtener una imagen y no la última (la más reciente). ¿Alguien puede mostrarme cómo obtener la última imagen?


Aquí hay una versión en Swift que solicita los datos y los convierte en un UIImage, ya que la versión proporcionada devuelve un UIImage vacío cada vez

let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)] let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) if let lastAsset: PHAsset = fetchResult.lastObject as? PHAsset { let manager = PHImageManager.defaultManager() let imageRequestOptions = PHImageRequestOptions() manager.requestImageDataForAsset(lastAsset, options: imageRequestOptions) { (let imageData: NSData?, let dataUTI: String?, let orientation: UIImageOrientation, let info: [NSObject : AnyObject]?) -> Void in if let imageDataUnwrapped = imageData, lastImageRetrieved = UIImage(data: imageDataUnwrapped) { // do stuff with image } } }


Bueno, aquí hay una solución de cómo cargar la última imagen de la galería con Swift 3 chicos:

func loadLastImageThumb(completion: @escaping (UIImage) -> ()) { let imgManager = PHImageManager.default() let fetchOptions = PHFetchOptions() fetchOptions.fetchLimit = 1 fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions) if let last = fetchResult.lastObject { let scale = UIScreen.main.scale let size = CGSize(width: 100 * scale, height: 100 * scale) let options = PHImageRequestOptions() imgManager.requestImage(for: last, targetSize: size, contentMode: PHImageContentMode.aspectFill, options: options, resultHandler: { (image, _) in if let image = image { completion(image) } }) } }

Si necesita más velocidad, también puede usar PHImageRequestOptions y configurarlos:

options.deliveryMode = .fastFormat options.resizeMode = .fast

Y esta es la forma de obtenerlo en su viewController (debe reemplazar GalleryManager.manager con su clase):

GalleryManager.manager.loadLastImageThumb { [weak self] (image) in DispatchQueue.main.async { self?.galleryButton.setImage(image, for: .normal) } }


Consulte la respuesta de Liam. fullScreenImage devolverá una imagen escalada que se ajuste al tamaño de pantalla de su dispositivo. Para obtener el tamaño de imagen real:

ALAssetRepresentation *representation = [alAsset defaultRepresentation]; ALAssetOrientation orientation = [representation orientation]; UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullResolutionImage] scale:[representation scale] orientation:(UIImageOrientation)orientation];

Citando la referencia de clase ALAssetRepresentation de Apple en fullResolutionImage :

Para crear un objeto UIImage rotado correctamente desde CGImage, use imageWithCGImage: scale: orientation: o initWithCGImage: scale: orientation :, pasando los valores de orientación y escala.


El ejemplo de iBrad incluye un fragmento iOS8 que aparentemente funciona, pero me encontré confundido por el tipo de devolución que describió. Aquí hay un fragmento que captura la última imagen, incluidas las opciones para los requisitos de versión y tamaño.

Cabe destacar la posibilidad de solicitar una versión específica (original, actual) y tamaño. En mi caso, como deseo aplicar la imagen devuelta a un botón, solicito su tamaño y escala para que se ajuste al botón al que lo estoy aplicando:

PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init]; fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]]; PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions]; PHAsset *lastAsset = [fetchResult lastObject]; [[PHImageManager defaultManager] requestImageForAsset:lastAsset targetSize:self.photoLibraryButton.bounds.size contentMode:PHImageContentModeAspectFill options:PHImageRequestOptionsVersionCurrent resultHandler:^(UIImage *result, NSDictionary *info) { dispatch_async(dispatch_get_main_queue(), ^{ [[self photoLibraryButton] setImage:result forState:UIControlStateNormal]; }); }];


El siguiente código funciona con iOS7 e iOS8. También verifica si hay una imagen en el filtro. Antes de ejecutar el código, debe verificar el permiso del álbum:

// get the latest image from the album -(void)getLatestPhoto { NSLog(@"MMM TGCameraViewController - getLatestPhoto"); ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; // Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos. [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { // Within the group enumeration block, filter to enumerate just photos. [group setAssetsFilter:[ALAssetsFilter allPhotos]]; // For this example, we''re only interested in the last item [group numberOfAssets]-1 = last. if ([group numberOfAssets] > 0) { [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:[group numberOfAssets]-1] options:0 usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) { // The end of the enumeration is signaled by asset == nil. if (alAsset) { ALAssetRepresentation *representation = [alAsset defaultRepresentation]; // Do something interesting with the AV asset. UIImage *img = [UIImage imageWithCGImage:[representation fullScreenImage]]; // use the photo here ... // we only need the first (most recent) photo -- stop the enumeration *innerStop = YES; } }]; } } failureBlock: ^(NSError *error) { // Typically you should handle an error more gracefully than this. NSLog(@"No groups"); }]; }

(Este código es una versión modificada desde here ).


Encontré un error tipográfico que me da vergüenza admitirme más de lo que debería haberlo imaginado. Tal vez salvará a alguien más en algún momento.

A esta línea le faltaban dos puntos después de indexSetWithIndex :

[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:[group numberOfAssets] - 1]options:0 usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {


Esta es una combinación de las respuestas de iBrad y Javier (que funcionó muy bien), pero obtengo el recurso miniatura en lugar de la imagen de resolución completa. Algunos otros pueden encontrar esto útil.

- (void)setCameraRollImage { ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { [group setAssetsFilter:[ALAssetsFilter allPhotos]]; if ([group numberOfAssets] > 0) { // Chooses the photo at the last index [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:([group numberOfAssets] - 1)] options:0 usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) { // The end of the enumeration is signaled by asset == nil. if (alAsset) { UIImage *latestPhoto = [UIImage imageWithCGImage:[alAsset thumbnail]]; [self.cameraRollButton setImage:latestPhoto forState:UIControlStateNormal]; } }]; } } failureBlock: ^(NSError *error) { }]; }


Este es un enfoque muy bueno, pero uno de los problemas es que tienes que ser capaz de instanciar PHPhotoLibrary y las otras clases de PHPhoto en tiempo de ejecución porque de lo contrario habrá errores de enlace en iOS 7.XX Solo quería señalar eso porque estoy corriendo en estos temas ahora.

También creo que es necesario un enlace débil en el marco de Photos para que la aplicación se ejecute en ambos dispositivos con iOS 8.XX e iOS 7.XX instalados (aunque aún no lo he probado).

Uno de los problemas con los que me estoy enfrentando es cómo crear una instancia de PHPhotoLibrary en tiempo de ejecución. ¿Alguien tiene fragmentos de código para eso?

En realidad, para la aplicación en la que estaba trabajando, tuve que escribir finalmente el código de tiempo de ejecución para crear una instancia de la clase PHPhotoLibrary y llamar a los métodos de framework PHotos para que la aplicación se ejecutara tanto en iOS 7.xx como en iOS 8.xx Alguien más puede toparse con el mismo problemas, así que proporcioné el código a continuación ->

// PHPhotoLibrary_class will only be non-nil on iOS 8.x.x Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary"); if (PHPhotoLibrary_class) { /** * iOS 8..x. . code that has to be called dynamically at runtime and will not link on iOS 7.x.x ... [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title]; } completionHandler:^(BOOL success, NSError *error) { if (!success) { NSLog(@"Error creating album: %@", error); } }]; */ // dynamic runtime code for code chunk listed above id sharedPhotoLibrary = [PHPhotoLibrary_class performSelector:NSSelectorFromString(@"sharedPhotoLibrary")]; SEL performChanges = NSSelectorFromString(@"performChanges:completionHandler:"); NSMethodSignature *methodSig = [sharedPhotoLibrary methodSignatureForSelector:performChanges]; NSInvocation* inv = [NSInvocation invocationWithMethodSignature:methodSig]; [inv setTarget:sharedPhotoLibrary]; [inv setSelector:performChanges]; void(^firstBlock)() = ^void() { Class PHAssetCollectionChangeRequest_class = NSClassFromString(@"PHAssetCollectionChangeRequest"); SEL creationRequestForAssetCollectionWithTitle = NSSelectorFromString(@"creationRequestForAssetCollectionWithTitle:"); [PHAssetCollectionChangeRequest_class performSelector:creationRequestForAssetCollectionWithTitle withObject:albumName]; }; void (^secondBlock)(BOOL success, NSError *error) = ^void(BOOL success, NSError *error) { if (success) { [assetsLib enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) { if (group) { NSString *name = [group valueForProperty:ALAssetsGroupPropertyName]; if ([albumName isEqualToString:name]) { groupFound = true; handler(group, nil); } } } failureBlock:^(NSError *error) { handler(nil, error); }]; } if (error) { NSLog(@"Error creating album: %@", error); handler(nil, error); } }; // Set the first and second blocks. [inv setArgument:&firstBlock atIndex:2]; [inv setArgument:&secondBlock atIndex:3]; [inv invoke]; } else { // code that always creates an album on iOS 7.x.x but fails // in certain situations such as if album has been deleted // previously on iOS 8...x. . [assetsLib addAssetsGroupAlbumWithName:albumName resultBlock:^(ALAssetsGroup *group) { handler(group, nil); } failureBlock:^(NSError *error) { NSLog( @"Failed to create album: %@", albumName); handler(nil, error); }]; }


Este fragmento de código obtendrá la última imagen del carrete de la cámara (iOS 7 y siguientes) :

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; // Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos. [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { // Within the group enumeration block, filter to enumerate just photos. [group setAssetsFilter:[ALAssetsFilter allPhotos]]; // Chooses the photo at the last index [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) { // The end of the enumeration is signaled by asset == nil. if (alAsset) { ALAssetRepresentation *representation = [alAsset defaultRepresentation]; UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullScreenImage]]; // Stop the enumerations *stop = YES; *innerStop = YES; // Do something interesting with the AV asset. [self sendTweet:latestPhoto]; } }]; } failureBlock: ^(NSError *error) { // Typically you should handle an error more gracefully than this. NSLog(@"No groups"); }];

iOS 8 y superior:

PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init]; fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]]; PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions]; PHAsset *lastAsset = [fetchResult lastObject]; [[PHImageManager defaultManager] requestImageForAsset:lastAsset targetSize:self.photoLibraryButton.bounds.size contentMode:PHImageContentModeAspectFill options:PHImageRequestOptionsVersionCurrent resultHandler:^(UIImage *result, NSDictionary *info) { dispatch_async(dispatch_get_main_queue(), ^{ [[self photoLibraryButton] setImage:result forState:UIControlStateNormal]; }); }];


Gracias por su respuesta iBrad Apps.

Solo quería señalar una prevención de errores para el caso especial cuando el usuario no tiene imágenes en su rollo de foto (caso extraño que conozco):

// Within the group enumeration block, filter to enumerate just photos. [group setAssetsFilter:[ALAssetsFilter allPhotos]]; //Check that the group has more than one picture if ([group numberOfAssets] > 0) { // Chooses the photo at the last index [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:([group numberOfAssets] - 1)] options:0 usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) { // The end of the enumeration is signaled by asset == nil. if (alAsset) { ALAssetRepresentation *representation = [alAsset defaultRepresentation]; UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullScreenImage]]; [self.libraryButton setImage:latestPhoto forState:UIControlStateNormal]; } }]; } else { //Handle this special case }


Sobre la base de la respuesta de iBrad, aquí hay una versión rápida y sucia de Swift que funciona para mí en iOS 8.1:

let imgManager = PHImageManager.defaultManager() var fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] if let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) { imgManager.requestImageForAsset(fetchResult.lastObject as PHAsset, targetSize: self.destinationImageView.frame.size, contentMode: PHImageContentMode.AspectFill, options: nil, resultHandler: { (image, _) in self.destinationImageView.image = image }) }

Nota : esto requiere iOS 8.0+. Asegúrese de vincular el marco de Fotos y agregar "importar fotos" en su archivo.


Una gran respuesta de iBrad, funcionó casi perfectamente para mí. La excepción es que devolvía las imágenes a su orientación original (por ejemplo, al revés, -90 °, etc.).

Para arreglar esto simplemente cambié fullResolutionImage a fullScreenImage .

Aquí:

UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullScreenImage]];

Ahora funciona como un regalo.


Versión de Xamarin.iOS de la respuesta aceptada (cómo obtener la última imagen), incluidos todos los avisos de otras respuestas:

private void ChooseLastTakenPictureImplementation() { var library = new ALAssetsLibrary(); // Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos. library.Enumerate(ALAssetsGroupType.SavedPhotos, (ALAssetsGroup assetsGroup, ref bool stop) => { if (stop || assetsGroup == null) { return; } //Xamarin does not support ref parameters in nested lamba expressions var lambdaStop = false; //Check that the group has more than one picture if (assetsGroup.Count > 0) { // Within the group enumeration block, filter to enumerate just photos. assetsGroup.SetAssetsFilter(ALAssetsFilter.AllPhotos); // Chooses the photo at the last index assetsGroup.Enumerate(NSEnumerationOptions.Reverse, (ALAsset result, int index, ref bool innerStop) => { // The end of the enumeration is signaled by asset == nil. if (result != null) { var representation = result.DefaultRepresentation; var latestPhoto = new UIImage(representation.GetImage(), representation.Scale, (UIImageOrientation)representation.Orientation); // Stop the enumerations lambdaStop = innerStop = true; // Do something interesting with the AV asset. HandleImageAutoPick(latestPhoto); } }); stop = lambdaStop; return; } else { //Handle this special case where user has no pictures } }, error => { // Typically you should handle an error more gracefully than this. Debug.WriteLine(error.Description); }); }