如何比较 PHAsset 和 UIImage

2024-01-08

我已经转换了一些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];
                            }];

现在我想做这样的事情:

[selectedAssets removeObject:image];

where selectedAssets是一个数组PHAsset and image is an 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];
}

但这不起作用!


您不应该比较图像,而应该比较 PHAssets 或它们唯一有用的名为 localIdentifier 的部分。

您正在寻找的用于区分资产的东西称为本地标识符 https://developer.apple.com/library/ios/documentation/Photos/Reference/PHObject_Class/index.html#//apple_ref/occ/instp/PHObject/localIdentifierPHAsset 的财产。

Apple 文档将其定义为:

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];
    }
}];

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何比较 PHAsset 和 UIImage 的相关文章

  • 是什么导致了这个 iPhone 崩溃日志?

    我有点卡住了 需要解决这个问题 因为我的一个应用程序出现了随机崩溃 而这些崩溃并不总是能够重现 这是崩溃日志之一 Incident Identifier 59865612 9F00 44EA 9474 2BF607AD662E CrashR
  • UISplitViewController - 推送模态视图

    使用 UISplitViewController 时推送模态视图的最佳实践是什么 您会从 RootViewController DetailViewController 还是直接从应用程序委托推送 理想情况下 我想要实现的功能是在基于某些条
  • 无法将 admob 与 firebase iOS/Android 项目链接

    我有两个帐户 A 和 B A 是在 Firebase 上托管 iOS Android unity 手机游戏的主帐户 B 用于将 admob 集成到 iOS Android 手机游戏中 我在尝试将 admob 分析链接到 Firebase 项
  • 如何在 Apple Watch Extension/App 和 iOS App 之间建立通信通道

    我正在探索 WatchKit SDK 当我有 WatchKit 应用程序时 是否可以在 WatchKit 应用程序上从 iPhone 应用程序设置值 例如文本 设置 我可以从 iPhone 应用程序调用 WatchKit 应用程序扩展中的函
  • 这个错误是无效上下文0x0吗?

    我在ViewDidLoad中编写了以下代码 Implement viewDidLoad to do additional setup after loading the view typically from a nib void view
  • Swift - 选择值后隐藏 pickerView

    我发现了类似的问题 他们的答案很有帮助 但我坚持最后一件事 我试图在点击字段时显示 pickerView 然后选择数据时 我希望 pickerView 隐藏 我可以从 pickerView 获取数据来隐藏 但是 pickerView 后面仍
  • iOS 8 中的 UISplitViewController 状态恢复

    在 iOS 8 上 UISplitViewController 似乎可以保存和恢复其子视图的状态 例如 主视图是否隐藏 这是不可取的 因为我的应用程序应该始终以横向方式显示主视图 并始终以纵向方式隐藏它 如果用户以横向模式关闭应用程序 保存
  • 如何从代码隐藏中设置 CarouselView 的项目?

    我有一个 CarouselView 它绑定到图像的 ItemsSource 但我想通过更改 CarouselView 的索引来更改当前显示的图像 我尝试使用 CarouselView Position 作为必须选择的元素的索引 但不幸的是这
  • 无法使用 Xamarin 和 WCF 访问 Web 服务

    我想使用 Xamarin 和 WCF 来使用公共 Web 服务 对于这个演示 我将使用Xamarin iOS 这是我试图使用的 公共 网络服务 http www webservicex net globalweather asmx WSDL
  • 在 Swift 中自动移动 UISlider

    我想在按下按钮时将 UISlider 从 minValue 循环移动到 maxValue 并在再次按下按钮时将其停止在当前位置 我想使用 Swift 我遇到的主要问题是函数 slider setValue 太快了 我希望动画更慢 IBAct
  • 混合静态和动态 UITableViewController 内容会导致 NSRangeException

    我一直在寻找这个错误 并找到了一些具有类似行为的帖子 但没有解决问题的解决方案 我有一个 UITableViewController 在 SB 中声明为静态 它具有以下部分 第 0 部分 配方 是静态的 有 4 个单元格 第 1 部分 口味
  • iPhone 快照,包括键盘

    我正在寻找拍摄整个 iPhone 屏幕 包括键盘 的正确方法 我找到了一些截取屏幕的代码 CGRect screenCaptureRect UIScreen mainScreen bounds UIView viewWhereYouWant
  • 如何将音乐从我的应用程序切换到 iPod

    我在用MusicPlayerController我的应用程序中的对象来播放音乐 我知道当 iPhone ipod 应用程序终止时 可以继续播放我的应用程序音乐 我该怎么做 这涉及到一些事情 您必须在两种音乐播放器之间进行选择 应用程序音乐播
  • 检查 touchend 是否在拖动后出现

    我有一些代码可以更改表的类 在手机上 有时表格对于屏幕来说太宽 用户将拖动 滚动来查看内容 但是 当他们触摸并拖动表格时 每次拖动都会触发 touchend 如何测试触摸端是否是触摸拖动的结果 我尝试跟踪dragstart和dragend
  • 我什么时候应该对 IBOutlet 使用弱或强限定符? [复制]

    这个问题在这里已经有答案了 可能的重复 ARC 下 IBOutlets 应该强还是弱 https stackoverflow com questions 7678469 should iboutlets be strong or weak
  • 在 Instruments 中查找内存泄漏行

    我是 iOS 中的仪器新手 我正在尝试使用 Xcode 4 5 2 并按照本教程查找仪器中的内存泄漏 http soulwithmobiletechnology blogspot sg 2011 04 how to check memory
  • 对使用phonegap和钛的质疑[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 最近我听说了 PhoneGap 和 Titanium 移动网络应用程序的开发 我分析了这两个 Web 应用程序 并了解了如何使用它们以
  • 将 iPhone 上的 stderr 写入文件和控制台

    我正在遵循答案中的建议here https stackoverflow com questions 5179108 iphone how to read application logs from device用于将 iOS 设备上的 NS
  • 为什么这个 SKPhysicsJointPin 不能将这 2 个精灵保持在一起?

    我显然不太了解 SKPhysicsJoint 但是除了 Apple 文档之外 网上的信息还很少 下面的代码有什么问题 我认为应该保持头部和颈部永久连接 我的意图是它们就像两张带有大头针的纸 这样它们可以旋转一点 但不仅仅是完全分开 当我运行
  • ActionScript、NetStream.Play.Failed iOS AIR 移动设备

    我正在尝试以类似于 Tiberiu Ionu Stan http stackoverflow com questions 2036107 aac mp4 not working in actionscript 3s netstream 的方

随机推荐