Comment obtenir seulement des images dans le rouleau de l'appareil photo en utilisant le cadre de Photos
le code suivant charge des images qui sont également localisées sur iCloud ou les images de flux. Comment peut-on limiter la recherche aux seules images sur la pellicule?
var assets = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil)
8 réponses
après avoir ajouté le rouleau de caméra et les albums de flux de photos, Apple a ajouté le PHAssetCollectionSubtype
types d'iOS 8.1:
PHAssetCollectionSubtypeAlbumMyPhotoStream
(avecPHAssetCollectionTypeAlbum
) - va chercher l'album Photo Stream.PHAssetCollectionSubtypeSmartAlbumUserLibrary
(avecPHAssetCollectionTypeSmartAlbum
) - extrait de l'album pellicule.
N'ont pas testé si c'est rétrocompatible avec iOS 8.0.x cependant.
a travers quelques expérimentations nous avons découvert une propriété cachée non listée dans la documentation (assetSource
). Fondamentalement, vous devez faire une demande de fetch régulière, puis utiliser un prédicat pour filtrer ceux du rouleau de caméra. Cette valeur devrait être de 3.
exemple de code:
//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)
Si vous utilisez votre propre PHCachingImageManager
au lieu du PHImageManager
instance alors quand vous appelez requestImageForAsset:targetSize:contentMode:options:resultHandler:
vous pouvez définir une option dans PHImageRequestOptions
pour spécifier que l'image est locale.
networkaccess allowed La propriété
une valeur booléenne qui spécifie si les Photos peuvent télécharger l'image demandée à partir d'iCloud.
networkaccess allowed
Discussion
si oui, et le l'image demandée n'est pas stockée sur le périphérique local, les photos téléchargent l'image à partir d'iCloud. Pour être informé de la progression du téléchargement, utilisez la propriété progressHandler pour fournir un bloc que Photos appelle périodiquement lors du téléchargement de l'image. Si non (par défaut), et que l'image n'est pas sur le périphérique local, la valeur PHImageResultIsInCloudKey dans le dictionnaire d'information du gestionnaire indique que l'image n'est pas disponible à moins que vous n'activiez l'accès au réseau.
si vous cherchez comme moi le code de L'Objectif C, et aussi que vous n'avez pas obtenu la réponse de la nouvelle bibliothèque / cadre de Photo comme vous obteniez le code d'AssetsLibrary déprécié, alors cela vous aidera: 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
Objectif C
Variables Globales:
NSArray *imageArray;
NSMutableArray *mutableArray;
méthode ci-dessous vous aidera à:
-(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
}
ceci peut aider. Vous pouvez utiliser votre propre modèle de données à la place D'AlbumModel que j'ai utilisé.
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
}
Voici la version Objective - c fournie par 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;
}
Où vous pouvez saisir détails suivants
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**
Apple demo lien
Déclarez votre propriété
@property (nonatomic, strong) NSArray *sectionFetchResults;
@property (nonatomic, strong) PHFetchResult *assetsFetchResults;
@property (nonatomic, strong) PHAssetCollection *assetCollection;
@property (nonatomic, strong) NSMutableArray *numberOfPhotoArray;
je me suis cogné la tête à cause de ça aussi. Je n'ai trouvé aucun moyen de filtrer pour seulement les actifs sur l'appareil avec fetchAssetsWithMediaType ou fetchAssetsInAssetCollection. Je suis en mesure d'utiliser requestContentEditingInputWithOptions ou requestigedataforasset pour déterminer si l'actif est sur l'appareil ou non, mais c'est asynchrone et semble utiliser beaucoup trop de ressources à faire pour chaque actif de la liste. Il doit y avoir une meilleure façon.
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 vous ne voulez pas vous fier à une API non documentée, regardez [asset canPerformEditOperation:PHAssetEditOperationContent]
. Ceci ne retourne true que si l'original complet est disponible sur l'appareil.
certes, c'est aussi fragile, mais les tests montrent que cela fonctionne pour tous les types d'assetSource (photostream, iTunes sync, etc.).