问题描述
我已经将一些 PHAsset
转换为 UIImage
:
I have converted some PHAsset
to UIImage
:
PHImageManager *manager = [PHImageManager defaultManager];
[manager requestImageForAsset:asset
targetSize:PHImageManagerMaximumSize
contentMode:PHImageContentModeDefault
options:requestOptions
resultHandler:^void(UIImage *image, NSDictionary *info) {
convertedImage = image;
[images addObject:convertedImage];
}];
现在我想做这样的事情:
Now I want to do something like that:
[selectedAssets removeObject:image];
其中 selectedAssets
是 PHAsset
的数组,image
是 UIImage
where selectedAssets
is an array of PHAsset
and image
is an UIImage
所以我像这样实现了 isEqual:
so I have implemented the isEqual like that:
- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![[other class] isEqual:[self class]])
return NO;
NSData *data1 = UIImagePNGRepresentation(self.image);
NSData *data2 = UIImagePNGRepresentation(((TINSelectedImage*)other).image);
return [data1 isEqual:data2];
}
但它不起作用!
推荐答案
你不应该比较图像,你应该比较 PHAssets 或者它们唯一有用的部分叫做 localIdentifier.
You should not compare images, you should instead compare PHAssets or their only useful part named localIdentifier.
您正在寻找区分资产的东西称为 localIdentifier 属性.
The thing that you are looking for to distinguish between assets is called localIdentifier property of PHAsset.
Apple Docs 将其定义为:
The Apple Docs define it as:
A unique string that persistently identifies the object. (read-only)
对不起,这个答案有点宽泛,因为我不喜欢你在这里的方法.
Sorry this answer will be a bit broad because I don't like your approach here.
如果我是你,我会这样做:
If I were you, I'd do it like this:
首先创建一个自定义类,我们将其命名为 PhotoInfo.(如果您对保留有关照片的大量信息不感兴趣,您实际上不必这样做.如果是这种情况,如果您愿意,请直接使用 PHAssets 的 PFFetchResults.不过,我将使用 CustomClass).
First Create a Custom Class, let's name it PhotoInfo. (You don't really have to do this if you are not interested in keeping a lot of info about your photos. If that's the case, use the PFFetchResults of PHAssets directly if you want to. I will however go with CustomClass).
在 PhotoInfo.h 中:
in PhotoInfo.h:
#import <Foundation/Foundation.h>
@interface PhotoInfo : NSObject
@property NSString *localIdentifier;
@end
现在不再使用图像数组,而是使用您创建的包含 localIdentifier 的自定义类.像这样:
Now instead of using an array of images, use this custom class you created which will contain localIdentifier. Like this:
PhotoInfo *photo = [[PhotoInfo alloc] init];
photo.localIdentifier = asset.localIdentifier;
假设您想从图库中获取图像,您可以执行以下操作:
Let's say you want to fetch images from gallery, you would do something like this:
-(PHFetchResult*) getAssetsFromLibrary
{
PHFetchResult *allPhotos;
PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc] init];
allPhotosOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; //Get images sorted by creation date
allPhotos = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:allPhotosOptions];
return allPhotos;
}
要填充数据源,请执行以下操作:
To populate your dataSource, you do something like:
NSMutableArray *yourPhotoDataSource = [[NSMutableArray alloc] init];
PHFetchResult * assets = [self getAssetsFromLibrary];
for(PHAsset *asset in assets)
{
PhotoInfo *photo = [PhotoInfo new];
photo.localIndentifier = asset.localIdentifier;
[yourPhotoDataSource addObject:photo];
}
现在假设您必须在某处显示这些图像,并且您需要一个实际图像,因此您将执行以下操作来获取图像:
Now let's say you have to display those images somewhere and you need an actual image for that so you will do something like this to get the image:
-(void) getImageForAsset: (PHAsset *) asset andTargetSize: (CGSize) targetSize andSuccessBlock:(void (^)(UIImage * photoObj))successBlock {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PHImageRequestOptions *requestOptions;
requestOptions = [[PHImageRequestOptions alloc] init];
requestOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
requestOptions.synchronous = true;
PHImageManager *manager = [PHImageManager defaultManager];
[manager requestImageForAsset:asset
targetSize:targetSize
contentMode:PHImageContentModeDefault
options:requestOptions
resultHandler:^void(UIImage *image, NSDictionary *info) {
@autoreleasepool {
if(image!=nil){
successBlock(image);
}
}
}];
});
}
现在假设您要在 tableView 中显示这些图像,在 cellForRowAtIndexPath 中,像这样调用上述方法:
Now let's say you are displaying those images in a tableView, in your cellForRowAtIndexPath, call the above mentioned method like this:
//Show a spinner
// Give a customizable size for image. Why load the memory with full image if you don't need to show it?
[self getImageForAsset:asset andTargetSize:yourDesiredCGSizeOfImage andSuccessBlock:^(UIImage *photoObj) {
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI of cell
//Hide the spinner
cell.thumbNail.image = photoObj;
});
}];
现在,您正在以流畅的用户体验异步加载图像,并通过仅显示需要的图像而不是存储所有图像来节省内存.(您可以通过引入缓存来提高性能,但这不是这里的重点).
Now you are loading images asynchronously with smooth user Experience and saving memory as well by showing only the images which are needed instead of storing all of them. (You can make the performance even better by introducing caching but that's not the point here).
最后解决您的问题,要删除某个图像,您只需要 localIdentifier,因为它对于每个 PHAsset 或索引都是唯一的.
Finally getting to your question, to remove a certain image you will do only need the localIdentifier because it is unique for every PHAsset or Index.
假设您要删除 tableView 中的某个单元格,该单元格显示了您现在要删除的特定图像.
Let's assume you are deleting some cell at your tableView which is showing that specific image which you now want to remove.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PhotoInfo *photo = [yourPhotoDataSource objectAtIndex:indexPath.row];
[yourPhotoDataSource removeObject:photo];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
如果您不使用 TableView/CollectionView 并且不知道对象的索引,您可以在数组上使用快速枚举,但您必须知道要删除的对象的 localIdentifier:
If you are not using a TableView/CollectionView and do not know the index of the object, you can use fast enumeration on your array but then you must know the localIdentifier of the object you wanna delete:
-(void) deletePhotoWithIdentifier:(NSString *) identifierStr{
NSMutableArray *dummyArray = [[NSMutableArray alloc] initWithArray:yourPhotoDataSource]; //created because we can't modify the array we are iterating on. Otherwise it crashes.
[dummyArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(PhotoInfo *p, NSUInteger index, BOOL *stop) {
if ([p.localIndentifier isEqualToString:idenfierStr]) {
[yourPhotoDataSource removeObjectAtIndex:index];
}
}];
}
这篇关于如何将 PHAsset 与 UIImage 进行比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!