FetchAssetsWithLocalIdentifiers 返回空数组
Posted
技术标签:
【中文标题】FetchAssetsWithLocalIdentifiers 返回空数组【英文标题】:FetchAssetsWithLocalIdentifiers returns empty array 【发布时间】:2016-09-17 16:39:27 【问题描述】:我正在使用Photos.Framework
将相机拍摄的照片保存到我的图库中并检索它们。
这是我用来存储照片的代码:
__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 确实更糟,因为几乎所有的 fetch 结果都是空的)。
我读过类似的东西是以前版本的 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 == %@".
并且总是相同的结果,很多时候获取结果是空的。
知道发生了什么吗?
【问题讨论】:
你找到原因了吗?同样的事情发生在我身上 是的,原因是我在调用 onSuccess(placeHolder.localIdentifier);在 performChanges 块内而不是在 completionHandler 块内。我将用我的代码更新来回答我自己的问题,以便您检查。 感谢您的回答,我会检查您的回答:) 【参考方案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);
];
【讨论】:
既然标识符作为第一个参数传递给 fetchAssetCollectionsWithLocalIdentifiers,为什么我们需要为 localIdentifier 指定谓词?这似乎是多余的。以上是关于FetchAssetsWithLocalIdentifiers 返回空数组的主要内容,如果未能解决你的问题,请参考以下文章