如何将 PHAsset 与 UIImage 进行比较
Posted
技术标签:
【中文标题】如何将 PHAsset 与 UIImage 进行比较【英文标题】:How to compare PHAsset to UIImage 【发布时间】:2016-08-08 12:25:44 【问题描述】:我已将一些PHAsset
转换为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];
];
现在我想做这样的事情:
[selectedAssets removeObject:image];
其中selectedAssets
是PHAsset
的数组,image
是UIImage
所以我已经像这样实现了 isEqual:
- (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];
但它不起作用!
【问题讨论】:
【参考方案1】:您不应该比较图像,而应该比较 PHAsset 或其唯一有用的部分,名为 localIdentifier。
您正在寻找区分资产的东西称为 PHAsset 的 localIdentifier 属性。
Apple Docs 将其定义为:
A unique string that persistently identifies the object. (read-only)
抱歉,这个答案会有点宽泛,因为我不喜欢你的做法。
如果我是你,我会这样做:
首先创建一个自定义类,我们将其命名为 PhotoInfo。 (如果您对保留有关照片的大量信息不感兴趣,则实际上不必这样做。如果是这种情况,请直接使用 PHAssets 的 PFFetchResults。但是,我将使用 CustomClass)。
在 PhotoInfo.h 中:
#import <Foundation/Foundation.h>
@interface PhotoInfo : NSObject
@property NSString *localIdentifier;
@end
现在不要使用图像数组,而是使用您创建的包含 localIdentifier 的自定义类。像这样:
PhotoInfo *photo = [[PhotoInfo alloc] init];
photo.localIdentifier = asset.localIdentifier;
假设你想从图库中获取图片,你会这样做:
-(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;
要填充您的数据源,您可以执行以下操作:
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];
现在假设您必须在某处显示这些图像,并且您需要一个实际图像,因此您将执行以下操作来获取图像:
-(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 中,像这样调用上述方法:
//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;
);
];
现在,您可以异步加载图像,获得流畅的用户体验,同时通过仅显示需要的图像而不是存储所有图像来节省内存。 (您可以通过引入缓存来提高性能,但这不是重点)。
最后回答您的问题,要删除某个图像,您只需要 localIdentifier,因为它对于每个 PHAsset 或索引都是唯一的。
假设您正在删除 tableView 中的某个单元格,该单元格显示您现在要删除的特定图像。
- (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:
-(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 进行比较的主要内容,如果未能解决你的问题,请参考以下文章
使用本地图像 URL 或 UIIMage 获取 PHAsset?
与 UIActivitiViewController 共享图像(UIImage)的 PHAsset 丢失元数据(Exif 等)
如何使用 Swift 通过 PHAsset 访问 UIImage 的元数据
将PHAsset转换为UIImage后设置UiButton图像