ios - Cómo obtener solo imágenes en el rollo de la cámara utilizando el Marco de Fotos
swift photosframework (8)
A través de algunos experimentos descubrimos una propiedad oculta que no figura en la documentación ( assetSource
). Básicamente, tiene que hacer una solicitud de recuperación regular, luego usar un predicado para filtrar los del rollo de la cámara. Este valor debe ser 3.
Código de muestra:
//fetch all assets, then sub fetch only the range we need
var assets = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions)
assets.enumerateObjectsUsingBlock { (obj, idx, bool) -> Void in
results.addObject(obj)
}
var cameraRollAssets = results.filteredArrayUsingPredicate(NSPredicate(format: "assetSource == %@", argumentArray: [3]))
results = NSMutableArray(array: cameraRollAssets)
El siguiente código carga imágenes que también se encuentran en iCloud o las imágenes de transmisión. ¿Cómo podemos limitar la búsqueda a solo imágenes en el rollo de la cámara?
var assets = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil)
Aquí está la versión de Objective-c proporcionada por Apple.
-(NSMutableArray *)getNumberOfPhotoFromCameraRoll:(NSArray *)array{
PHFetchResult *fetchResult = array[1];
int index = 0;
unsigned long pictures = 0;
for(int i = 0; i < fetchResult.count; i++){
unsigned long temp = 0;
temp = [PHAsset fetchAssetsInAssetCollection:fetchResult[i] options:nil].count;
if(temp > pictures ){
pictures = temp;
index = i;
}
}
PHCollection *collection = fetchResult[index];
if (![collection isKindOfClass:[PHAssetCollection class]]) {
// return;
}
// Configure the AAPLAssetGridViewController with the asset collection.
PHAssetCollection *assetCollection = (PHAssetCollection *)collection;
PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
self. assetsFetchResults = assetsFetchResult;
self. assetCollection = assetCollection;
self.numberOfPhotoArray = [NSMutableArray array];
for (int i = 0; i<[assetsFetchResult count]; i++) {
PHAsset *asset = assetsFetchResult[i];
[self.numberOfPhotoArray addObject:asset];
}
NSLog(@"%lu",(unsigned long)[self.numberOfPhotoArray count]);
return self.numberOfPhotoArray;
}
Donde puedes agarrar los siguientes detalles
PHFetchResult *fetchResult = self.sectionFetchResults[1];
PHCollection *collection = fetchResult[6];
**value 1,6 used to get camera images**
**value 1,0 used to get screen shots**
**value 1,1 used to get hidden**
**value 1,2 used to get selfies**
**value 1,3 used to get recently added**
**value 1,4 used to get videos**
**value 1,5 used to get recently deleted**
**value 1,7 used to get favorites**
link demo de Apple
Declara tu propiedad
@property (nonatomic, strong) NSArray *sectionFetchResults;
@property (nonatomic, strong) PHFetchResult *assetsFetchResults;
@property (nonatomic, strong) PHAssetCollection *assetCollection;
@property (nonatomic, strong) NSMutableArray *numberOfPhotoArray;
Después de agregar los álbumes de Camera Roll y Photo Stream, Apple agregó los siguientes tipos de PHAssetCollectionSubtype
en iOS 8.1:
PHAssetCollectionSubtypeAlbumMyPhotoStream
(junto conPHAssetCollectionTypeAlbum
):PHAssetCollectionTypeAlbum
el álbum de Photo Stream.PHAssetCollectionSubtypeSmartAlbumUserLibrary
(junto conPHAssetCollectionTypeSmartAlbum
): obtiene el álbum Camera Roll.
No he probado si esto es compatible con versiones anteriores con iOS 8.0.x sin embargo.
Esto puede ayudar. Puedes usar tu propio modelo de datos en lugar de AlbumModel que usé.
func getCameraRoll() -> AlbumModel {
var cameraRollAlbum : AlbumModel!
let cameraRoll = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil)
cameraRoll.enumerateObjects({ (object: AnyObject!, count: Int, stop: UnsafeMutablePointer) in
if object is PHAssetCollection {
let obj:PHAssetCollection = object as! PHAssetCollection
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
let assets = PHAsset.fetchAssets(in: obj, options: fetchOptions)
if assets.count > 0 {
let newAlbum = AlbumModel(name: obj.localizedTitle!, count: assets.count, collection:obj, assets: assets)
cameraRollAlbum = newAlbum
}
}
})
return cameraRollAlbum
}
Me he estado golpeando la cabeza por esto también. No he encontrado ninguna forma de filtrar solo los activos en el dispositivo con fetchAssetsWithMediaType o fetchAssetsInAssetCollection. Puedo usar requestContentEditingInputWithOptions o requestImageDataForAsset para determinar si el activo está en el dispositivo o no, pero esto es asíncrono y parece que está usando demasiados recursos para hacer por cada activo en la lista. Tiene que haber una mejor manera.
PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];
for (int i=0; i<[fetchResult count]; i++) {
PHAsset *asset = fetchResult[i];
[asset requestContentEditingInputWithOptions:nil
completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
if ([[info objectForKey:PHContentEditingInputResultIsInCloudKey] intValue] == 1) {
NSLog(@"asset is in cloud");
} else {
NSLog(@"asset is on device");
}
}];
}
Si está buscando, como yo, el código de Objective C, y tampoco recibió la Respuesta de la nueva biblioteca / Marco de fotos ya que estaba obteniendo el código obsoleto de AssetsLibrary, entonces esto lo ayudará a: Swift
Variables globales:
var imageArray: [AnyObject]
var mutableArray: [AnyObject]
convenience func getAllPhotosFromCamera() {
imageArray = [AnyObject]()
mutableArray = [AnyObject]()
var requestOptions: PHImageRequestOptions = PHImageRequestOptions()
requestOptions.resizeMode = .Exact
requestOptions.deliveryMode = .HighQualityFormat
requestOptions.synchronous = true
var result: PHFetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: nil)
NSLog("%d", Int(result.count))
var manager: PHImageManager = PHImageManager.defaultManager()
var images: [AnyObject] = [AnyObject](minimumCapacity: result.count)
// assets contains PHAsset objects.
var ima: UIImage
for asset: PHAsset in result {
// Do something with the asset
manager.requestImageForAsset(asset, targetSize: PHImageManagerMaximumSize, contentMode: .Default, options: requestOptions, resultHandler: {(image: UIImage, info: [NSObject : AnyObject]) -> void in
C objetivo
Variables globales:
NSArray *imageArray;
NSMutableArray *mutableArray;
El siguiente método te ayudará a:
-(void)getAllPhotosFromCamera
{
imageArray=[[NSArray alloc] init];
mutableArray =[[NSMutableArray alloc]init];
PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
requestOptions.synchronous = true;
PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];
NSLog(@"%d",(int)result.count);
PHImageManager *manager = [PHImageManager defaultManager];
NSMutableArray *images = [NSMutableArray arrayWithCapacity:[result count]];
// assets contains PHAsset objects.
__block UIImage *ima;
for (PHAsset *asset in result) {
// Do something with the asset
[manager requestImageForAsset:asset
targetSize:PHImageManagerMaximumSize
contentMode:PHImageContentModeDefault
options:requestOptions
resultHandler:^void(UIImage *image, NSDictionary *info) {
ima = image;
[images addObject:ima];
}];
}
imageArray = [images copy]; // You can direct use NSMutuable Array images
}
Si no desea confiar en una API no documentada, consulte [asset canPerformEditOperation:PHAssetEditOperationContent]
. Esto solo devuelve verdadero si el original completo está disponible en el dispositivo.
Es cierto que esto también es frágil, pero las pruebas muestran que funciona para todos los tipos de fuentes de recursos (secuencia de fotos, sincronización de iTunes, etc.).
Si usa su propio PHCachingImageManager
lugar de la instancia de PHImageManager
compartida, cuando llame a requestImageForAsset:targetSize:contentMode:options:resultHandler:
puede configurar una opción en PHImageRequestOptions
para especificar que la imagen es local.
networkAccessAllowed Property
Un valor booleano que especifica si las fotos pueden descargar la imagen solicitada desde iCloud.
networkAccessAllowed
Discusión
Si es SÍ, y la imagen solicitada no se almacena en el dispositivo local, Photos descarga la imagen de iCloud. Para recibir una notificación sobre el progreso de la descarga, use la propiedad progressHandler para proporcionar un bloque al que Photos llame periódicamente mientras descarga la imagen. Si NO (el valor predeterminado) y la imagen no se encuentra en el dispositivo local, el valor de PHImageResultIsInCloudKey en el diccionario de información del controlador de resultados indica que la imagen no está disponible a menos que habilite el acceso a la red.