web-dev-qa-db-fra.com

Comment obtenir uniquement des images dans la pellicule à l'aide de Photos Framework

Le code suivant charge les images qui sont également situées sur iCloud ou les images de flux. Comment pouvons-nous limiter la recherche aux seules images dans la pellicule?

var assets = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil)
23
William Falcon

Après quelques expériences, nous avons découvert une propriété cachée non répertoriée dans la documentation (assetSource). Fondamentalement, vous devez faire une requête d’extraction régulière, puis utiliser un prédicat pour filtrer celles du rouleau de caméra. Cette valeur devrait être 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)
5
William Falcon

Après avoir ajouté les albums Pellicule et Flux de photos, Apple a ajouté les types PHAssetCollectionSubtype suivants dans iOS 8.1:

  1. PHAssetCollectionSubtypeAlbumMyPhotoStream (avec PHAssetCollectionTypeAlbum) - récupère l'album Photo Stream.

  2. PHAssetCollectionSubtypeSmartAlbumUserLibrary (avec PHAssetCollectionTypeSmartAlbum) - récupère l'album Pellicule.

Nous n'avons pas testé si cela est rétro-compatible avec iOS 8.0.x cependant.

19
StatusReport

Si vous recherchez comme moi du code Objective C et que vous n'avez pas reçu la réponse de la nouvelle bibliothèque/Cadre photo car vous obteniez du code obsolète pour AssetsLibrary, ceci 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;

la 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
}
4
karan

Si vous utilisez votre propre PHCachingImageManager à la place de l'instance PHImageManager partagée, vous pouvez définir une option dans PHImageRequestOptions lorsque vous appelez requestImageForAsset:targetSize:contentMode:options:resultHandler: pour spécifier que l'image est locale.

networkAccessAllowed Propriété

Valeur booléenne indiquant si Photos peut télécharger l'image demandée à partir d'iCloud.

networkAccessAllowed

Discussion

Si la réponse est OUI et que l'image demandée n'est pas stockée sur le périphérique local, Photos télécharge l'image à partir d'iCloud. Pour être informé de la progression du téléchargement, utilisez la propriété progressHandler pour fournir un bloc qui appelle Photos régulièrement pendant le téléchargement de l’image. Si la valeur par défaut est NO et que l’image ne se trouve pas sur le périphérique local, la valeur PHImageResultIsInCloudKey du dictionnaire d’informations du gestionnaire de résultats indique que l’image n’est pas disponible, à moins que vous ne activiez l’accès réseau.

4
Grimxn

Cela peut aider. Vous pouvez utiliser votre propre modèle de données à la place de 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

        }
3
jamesthakid

Je me suis aussi cogné la tête. J'ai trouvé aucun moyen de filtrer uniquement les actifs sur le périphérique avec fetchAssetsWithMediaType ou fetchAssetsInAssetCollection. Je peux utiliser requestContentEditingInputWithOptions ou requestImageDataForAsset pour déterminer si l'actif se trouve sur le périphérique ou non, mais cela est asynchrone et semble utiliser beaucoup trop de ressources pour chaque actif de la liste. Il doit y avoir un meilleur moyen.

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");
                                   }
                               }];

}
0
Tom Kincaid

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 les 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**

Démo Apple lien

Déclarez votre bien

@property (nonatomic, strong) NSArray *sectionFetchResults;
@property (nonatomic, strong) PHFetchResult *assetsFetchResults;
@property (nonatomic, strong) PHAssetCollection *assetCollection;
@property (nonatomic, strong) NSMutableArray *numberOfPhotoArray;
0
karthikeyan