2016-09-17 522 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

是的,原因是我打电话给成功(placeHolder.localIdentifier);在performChanges块内而不是在completionHandler块内。我将用我的代码更新回答我自己的问题,以便您可以检查它。 – Wonton

+0

感谢您的回答,我将检查您的答案:) – StackOverflower

回答

1

我的问题是,我没有以正确的方式保存照片,我正在调用onSuccess(placeHolder.localIdentifier);在performChanges块内而不是在completionHandler块内。

这是我现在使用的代码保存照片:

__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