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