2016-09-17 7 views
3

Я использую Photos.Framework, чтобы сохранить фотографии, снятые с камеры, в мою галерею и получить их.FetchAssetsWithLocalIdentifiers возвращает пустой массив

Это код, я использую для хранения фотографий:

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

И это код, я использую, чтобы получить эту фотографию:

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

С помощью этой части кода , по образцу из 12 сохраненных фотографий (они в порядке в моем альбоме) 4 или 5 их локальных идентификаторов возвращают результаты пустой выборки. Это протестировано в iOS 8, iOS 9 и iOS 10 (с iOS 10 это действительно хуже, потому что почти все результаты выборки пустые).

Я читал, что что-то похожее на это было ошибкой в ​​предыдущих версиях iOS, но я думаю, теперь это не причина.

Я попытался с помощью этого метода для получения фотографий:

- (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; 
} 

Я попытался с PHAssetCollectionSubtypeAlbumMyPhotoStream вместо PHAssetCollectionSubtypeAny. И я пробовал с @"localIdentifier ==[cd] %@" вместо @"localIdentifier == %@". И всегда те же результаты, много раз результаты выборки пустые. Любая идея о том, что это происходит?

+0

Вы накануне нашли причину этого? То же самое происходит со мной – StackOverflower

+0

Да, причина в том, что я вызывал onSuccess (placeHolder.localIdentifier); внутри блока executeChanges вместо внутреннего блока finallyHandler. Я отвечу на свой вопрос с обновлением кода, чтобы вы могли его проверить. – Wonton

+0

Спасибо за ответ, я буду проверять ваш ответ :) – StackOverflower

ответ

1

Моя проблема заключалась в том, что я не сохранял фотографии в правильном направлении, я звонил вSuccess (placeHolder.localIdentifier); внутри блока executeChanges вместо внутреннего блока finallyHandler.

Это код, я использую в настоящее время, чтобы сохранить фотографии:

__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

Зачем нам нужно указывать предикат для localIdentifier, учитывая, что идентификаторы передаются в качестве первого параметра для fetchAssetCollectionsWithLocalIdentifiers? Кажется, он лишний. – nishant

Смежные вопросы