2016-09-17 1 views
3

J'utilise Photos.Framework pour enregistrer les photos prises depuis l'appareil photo dans ma galerie et pour les récupérer.FetchAssetsWithLocalIdentifiers renvoie le tableau vide

C'est le code que je utilise pour stocker les photos:

__block PHAssetCollection *album = [self getMyAlbumWithName:@"MyAlbumName"]; 
    if(album == nil) 
    { 
     [self makeAlbumWithTitle:@"MyAlbumName" onSuccess:^(NSString *AlbumId) { 

      album = [self getMyAlbumWithName:@"MyAlbumName"]; 
      [self addNewAssetWithImage:_imageToStore toAlbum:album onSuccess:^(NSString *ImageId) 
      { 
        _imageLocalIdentifier = imageId; 
      } onError:^(NSError *error) { 
       // No need to do anything 
      }]; 
     } onError:^(NSError *error) { 
      // No need to do anything 
     }]; 
    } 
    else 
    { 
     [self addNewAssetWithImage:_imageToStore toAlbum:album onSuccess:^(NSString *ImageId) 
     { 
      _imageLocalIdentifier = imageId; 
     } onError:^(NSError *error) { 
      // No need to do anything 
     }]; 
    } 

-(PHAssetCollection *)getMyAlbumWithName:(NSString*)AlbumName 
{ 
    PHFetchResult *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum 
                       subtype:PHAssetCollectionSubtypeAlbumRegular 
                      options:nil]; 
    NSLog(@"assetCollections.count = %lu", assetCollections.count); 
    if (assetCollections.count == 0) return nil; 

    __block PHAssetCollection * myAlbum; 
    [assetCollections enumerateObjectsUsingBlock:^(PHAssetCollection *album, NSUInteger idx, BOOL *stop) { 
    NSLog(@"album:%@", album); 
    NSLog(@"album.localizedTitle:%@", album.localizedTitle); 
    if ([album.localizedTitle isEqualToString:AlbumName]) { 
     myAlbum = album; 
     *stop = YES; 
     } 
    }]; 

    if (!myAlbum) return nil; 
    return myAlbum; 
} 

-(void)makeAlbumWithTitle:(NSString *)title onSuccess:(void(^)(NSString *AlbumId))onSuccess onError: (void(^)(NSError * error)) onError 
{ 
    //Check weather the album already exist or not 
    if (![self getMyAlbumWithName:title]) 
    { 
     [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 
      // Request editing the album. 
      PHAssetCollectionChangeRequest *createAlbumRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title]; 
      // Get a placeholder for the new asset and add it to the album editing request. 
      PHObjectPlaceholder * placeHolder = [createAlbumRequest placeholderForCreatedAssetCollection]; 
      if (placeHolder) 
      { 
       onSuccess(placeHolder.localIdentifier); 
      } 
     } completionHandler:^(BOOL success, NSError *error) { 
      NSLog(@"Finished adding asset. %@", (success ? @"Success" : error)); 
      if (error) 
      { 
       onError(error); 
      } 
     }]; 
    } 
} 

-(void)addNewAssetWithImage:(UIImage *)image 
        toAlbum:(PHAssetCollection *)album 
        onSuccess:(void(^)(NSString *ImageId))onSuccess 
        onError: (void(^)(NSError * error)) onError 
{ 
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 
     // Request creating an asset from the image. 
     PHAssetChangeRequest *createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image]; 
     // Request editing the album. 
     PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album]; 
     // Get a placeholder for the new asset and add it to the album editing request. 
     PHObjectPlaceholder * placeHolder = [createAssetRequest placeholderForCreatedAsset]; 
     [albumChangeRequest addAssets:@[ placeHolder ]]; 
     NSLog(@"%@",placeHolder.localIdentifier); 
     if (placeHolder) { 
      onSuccess(placeHolder.localIdentifier); 
     } 
    } completionHandler:^(BOOL success, NSError *error) { 
     NSLog(@"Finished adding asset. %@", (success ? @"Success" : error)); 
     if (error) { 
      onError(error); 
     } 
    }]; 
} 

Et c'est le code que je utilise pour récupérer cette photo:

PHImageManager *imgManager = [[PHImageManager alloc] init]; 
    PHFetchResult* fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[_imageLocalIdentifier] options:nil]; 
    if([fetchResult count] > 0) 
    { 
     PHAsset *asset = [fetchResult objectAtIndex:0]; 
     PHImageRequestOptions *option = [PHImageRequestOptions new]; 
     option.synchronous = NO; 
     option.version = PHImageRequestOptionsVersionCurrent; 
     option.networkAccessAllowed = YES; 
     option.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic; 
     option.resizeMode = PHImageRequestOptionsResizeModeFast; 
     [imgManager requestImageForAsset:asset 
           targetSize:CGSizeMake(CAMERA_GALLERY_SIZE, CAMERA_GALLERY_SIZE) 
          contentMode:PHImageContentModeDefault 
           options:option 
          resultHandler:^(UIImage *result, NSDictionary *info) { 
           [cell.photoIV setImage:result]; 
          }]; 
    } 

Avec ce morceau de code , sur un échantillon de 12 photos stockées (elles sont correctes dans mon album) 4 ou 5 de leurs identifiants locaux renvoie un résultat de recherche vide. Cela a été testé sur iOS 8, iOS 9 et iOS 10 (avec iOS 10, c'est pire car presque tous les résultats de recherche sont vides).

J'ai lu que quelque chose de similaire à ceci était un bug dans les versions précédentes d'iOS, mais je suppose que ce n'est pas la raison maintenant.

J'ai essayé avec cette méthode pour récupérer les photos:

- (PHAsset *)getAssetFromGallery:(NSString *)identifier 
{ 
    PHAsset *asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[identifier] options:nil].lastObject; 
    if(asset != nil) 
     return asset; 

    __block PHAsset *result; 
    PHFetchResult *userAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:nil]; 

    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init]; 
    [fetchOptions setPredicate:[NSPredicate predicateWithFormat:@"localIdentifier == %@", identifier]]; 

    [userAlbums enumerateObjectsUsingBlock:^(id _Nonnull objectCollection, NSUInteger idx, BOOL * _Nonnull stopCollectionEnumeration) { 

     PHAssetCollection *collection = nil; 
     if(![objectCollection isKindOfClass:[PHAssetCollection class]]) 
      return; 
     collection = (PHAssetCollection *)objectCollection; 

     PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:fetchOptions]; 
     [assetsFetchResult enumerateObjectsUsingBlock:^(id _Nonnull objectAsset, NSUInteger idx, BOOL * _Nonnull stopAssetEnumeration) { 
      PHAsset *asset = nil; 
      if(![objectAsset isKindOfClass:[PHAsset class]]) 
       return; 
      result = asset; 
      *stopAssetEnumeration = YES; 
      *stopCollectionEnumeration = YES; 
     }]; 

    }]; 

    return asset; 
} 

J'ai essayé avec PHAssetCollectionSubtypeAlbumMyPhotoStream au lieu de PHAssetCollectionSubtypeAny. Et j'ai essayé avec @"localIdentifier ==[cd] %@" au lieu de @"localIdentifier == %@". Et toujours les mêmes résultats, beaucoup de fois les résultats d'extraction sont vides. Une idée de ce qui se passe?

+0

Avez-vous trouvé la veille cause de cela? Même chose pour moi – StackOverflower

+0

Oui, la raison était que j'appelais onSuccess (placeHolder.localIdentifier); à l'intérieur du bloc performChanges au lieu de l'intérieur du bloc completionHandler. Je vais répondre à ma propre question avec ma mise à jour de code afin que vous puissiez le vérifier. – Wonton

+0

Merci de répondre, je vais vérifier votre réponse :) – StackOverflower

Répondre

1

Mon problème était que je n'étais pas en train d'enregistrer les photos de la bonne manière, j'appelais onSuccess (placeHolder.localIdentifier); à l'intérieur du bloc performChanges au lieu de l'intérieur du bloc completionHandler.

Voici le code que je utilise maintenant pour enregistrer les photos:

__block PHAssetCollection *album = [AuxiliaryFunctions getMyAlbumWithName:@"MyAlbumName" orWithIdentifier:@""]; 
if(album == nil) 
    [self makeAlbumWithTitle:@"MyAlbumName" onSuccess:^(NSString *AlbumId) { 

     album = [self getMyAlbumWithName:@"MyAlbumName" orWithIdentifier:AlbumId]; 
     [self addNewAssetWithImage:_imageToStore toAlbum:album onSuccess:^(NSString *ImageId) 
     { 
      _imageLocalIdentifier = imageId; 
     } onError:^(NSError *error) { 
      // No need to do anything 
     }]; 
    } onError:^(NSError *error) { 
     // No need to do anything 
    }]; 
else 
{ 
    [self addNewAssetWithImage:_imageToStore toAlbum:album onSuccess:^(NSString *ImageId) 
    { 
      _imageLocalIdentifier = imageId; 
    } onError:^(NSError *error) { 
     // No need to do anything 
    }]; 
} 


-(PHAssetCollection *)getMyAlbumWithName:(NSString*)AlbumName orWithIdentifier:(NSString *)identifier 
{ 
    PHFetchResult *assetCollections = nil; 
    if(![identifier isEqualToString:@""]) 
    { 
     PHFetchOptions *options = [PHFetchOptions new]; 
     options.predicate = [NSPredicate predicateWithFormat:@"localIdentifier = %@ OR title = %@", identifier, AlbumName]; 
     assetCollections = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[identifier] 
                       options:options]; 
    } 
    else 
    { 
     PHFetchOptions *options = [PHFetchOptions new]; 
     options.predicate = [NSPredicate predicateWithFormat:@"title = %@", AlbumName]; 
     assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum 
                        subtype:PHAssetCollectionSubtypeAny 
                        options:options]; 
    } 

    NSLog(@"assetCollections.count = %lu", assetCollections.count); 
    if (assetCollections.count == 0) return nil; 

    __block PHAssetCollection * myAlbum; 
    [assetCollections enumerateObjectsUsingBlock:^(PHAssetCollection *album, NSUInteger idx, BOOL *stop) { 
     NSLog(@"album:%@", album); 
     NSLog(@"album.localizedTitle:%@", album.localizedTitle); 
     if ([album.localizedTitle isEqualToString:AlbumName]) { 
      myAlbum = album; 
      *stop = YES; 
     } 
    }]; 

    if (!myAlbum) return nil; 
    return myAlbum; 
} 

-(void)makeAlbumWithTitle:(NSString *)title onSuccess:(void(^)(NSString *AlbumId))onSuccess onError: (void(^)(NSError * error)) onError 
{ 
    __block NSString *localIdentifier = @""; 
    //Check weather the album already exist or not 
    if (![self getMyAlbumWithName:title orWithIdentifier:@""]) 
    { 
     [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 
      // Request editing the album. 
      PHAssetCollectionChangeRequest *createAlbumRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title]; 
      // Get a placeholder for the new asset and add it to the album editing request. 
      PHObjectPlaceholder * placeHolder = [createAlbumRequest placeholderForCreatedAssetCollection]; 
      if (placeHolder) 
      { 
       localIdentifier = placeHolder.localIdentifier; 
       // This line was the problem 
       //onSuccess(localIdentifier); 
      } 
     } completionHandler:^(BOOL success, NSError *error) { 
      NSLog(@"Finished adding asset. %@", (success ? @"Success" : error)); 
      if(success) 
      { 
       onSuccess(localIdentifier); 
      } 
      if (error) 
      { 
       onError(error); 
      } 
     }]; 
    } 
} 

-(void)addNewAssetWithImage:(UIImage *)image 
        toAlbum:(PHAssetCollection *)album 
        onSuccess:(void(^)(NSString *ImageId))onSuccess 
        onError: (void(^)(NSError * error)) onError 
{ 
    __block NSString *localIdentifier = @""; 
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 
     // Request creating an asset from the image. 
     PHAssetChangeRequest *createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image]; 
     // Request editing the album. 
     PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album]; 
     // Get a placeholder for the new asset and add it to the album editing request. 
     PHObjectPlaceholder * placeHolder = [createAssetRequest placeholderForCreatedAsset]; 
     [albumChangeRequest addAssets:@[ placeHolder ]]; 
     NSLog(@"%@",placeHolder.localIdentifier); 
     if (placeHolder) { 
      localIdentifier = placeHolder.localIdentifier; 
      // This line was the problem 
      //onSuccess(localIdentifier); 
     } 
    } completionHandler:^(BOOL success, NSError *error) { 
     NSLog(@"Finished adding asset. %@", (success ? @"Success" : error)); 
     if(success) 
     { 
      onSuccess(localIdentifier); 
     } 
     if (error) 
     { 
      onError(error); 
     } 
    }]; 
} 
+0

Pourquoi avons-nous besoin de spécifier un prédicat pour localIdentifier étant donné que les identifiants sont transmis en tant que premier paramètre à fetchAssetCollectionsWithLocalIdentifiers? Cela semble être redondant. – nishant