使用 UIImageView 作为 NSMutableDictionary 中的键来查找布尔值

Posted

技术标签:

【中文标题】使用 UIImageView 作为 NSMutableDictionary 中的键来查找布尔值【英文标题】:Using UIImageView as key in NSMutableDictionary to look up boolean 【发布时间】:2013-02-17 21:26:39 【问题描述】:

标题几乎说明了一切。我想创建一个 NSMutableDictionary,在其中使用 UIImageViews 来查找布尔值。这是它的样子:

我的 .h 文件:

@interface ViewController : UIViewController
    UIImageView *image1;
    UIImageView *image2;
    NSMutableDictionary *isUseable;


@property (nonatomic, retain) IBOutlet UIImageView *image1;
@property (nonatomic, retain) IBOutlet UIImageView *image2;
@property (nonatomic, retain) NSMutableDictionary *isUseable;

我的 .m 文件:

@synthesize image1, image2;
@synthesize isUseable

- (void)viewDidLoad

    isUseable = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                 @NO, image1,
                 @NO, image2,nil];


-(void)runEvents
    if(some condition)
        [isUseable setObject:@YES forKey:(id)image1];
    

    //Use it later:
    if(isUseable[image1])
        //Do stuff
    

它可以编译,但是当我运行它时,我得到一个未捕获的异常 'NSInvalidArgumentException',原因:'-[UIImageView copyWithZone:]: unrecognized selector sent to instance。

我猜问题在于 NSDictionary 类复制了它的键。有没有办法让字典在这种情况下工作?如果没有,我应该如何设置我想要的查找?有什么想法/建议吗?

【问题讨论】:

【参考方案1】:

是的,问题是NSDictionary 中的密钥必须符合NSCopying 协议,而UIImage 不符合。

一种解决方案是给每张图片一个唯一的标签。然后使用图像的标签作为键(在将其包装在NSNumber 中之后)。

- (void)viewDidLoad 
    isUseable = [ @ @(image1.tag) : @NO, @(image2.tag) : @NO  mutableCopy];


-(void)runEvents 
    if(some condition) 
        [isUseable setObject:@YES forKey:@(image1.tag)];
    

    //Use it later:
    if(isUseable[@(image1.tag)]) 
        //Do stuff
    

只需添加代码即可查看每张图片的tag 属性。

【讨论】:

谢谢,这有帮助。我困惑了一段时间,直到我意识到我必须设置自己的标签值(我的错是没有像我应该的那样仔细阅读您的回复)。我也有点喜欢下面的哈希建议,因为我不必考虑想出自己的 ID。【参考方案2】:

rmaddy 说的很对:NSDictionary 必须符合 NSCopying 协议,而 UIImage 不符合。

我建议使用@(image.hash) 作为字典键。这就像UIImage 的指纹。

【讨论】:

使用hash 作为密钥可能有效。请记住,两个图像可能具有相同的hash 值。虽然只有几张图片,但机会很小。 应该注意.hash冲突在Objective-c中相当普遍。在处理 SHA256 之类的东西时,它们没有相同的抗碰撞性。如果您需要抗碰撞性,您可以获得 UIImage 的 SHA256。我在这里提供了一个关于如何做到这一点的答案:***.com/a/67627996/2057171【参考方案3】:

NSDictionaries 中的键必须符合 NSCopyingUIImageView 则不然。 您必须找到不同的密钥,或者您可以扩展UIImageView 以符合NSCopying。请参阅this answer on SO 了解如何使用UIImage

【讨论】:

【参考方案4】:

从图像中获取原始数据(不是重新渲染的 PNG 或 JPG 表示),然后通过内置的 common-crypto 运行它以获取数据的 SHA256,这将是您的密钥。

其他答案建议使用内置实例属性.hash,但它很容易发生冲突,并且最终会频繁发生(我们在其中一个应用程序中遇到了字符串冲突,并导致了严重的错误)。

#include <CommonCrypto/CommonDigest.h>

-(NSString *)keyFromImage:(UIImage *)image 

    NSData *imageData = (__bridge NSData *)CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
    
    unsigned char result[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256((__bridge const void *)imageData, (CC_LONG)imageData.length, result);
    
    NSMutableString *imageHash = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
    
    for(int i = 0; i<CC_SHA256_DIGEST_LENGTH; i++) 
        [imageHash appendFormat:@"%02x",result[i]];
    
    
    return imageHash;


【讨论】:

【参考方案5】:

根据您的对象的管理方式,您可以将其在内存中的地址用作键(这适用于 UIImageView 或 UIImage,因为关于此问题的一般性讨论似乎围绕非此即彼):

myDictionary[@((intptr_t)myObject)] = myValue;

【讨论】:

我过去在处理将图像附加到 NSMutableString 时使用它...我使用指向 NSTextAttachment 的指针作为将原始高清源图像引用到 NSTextAttachment 中使用的缩略图的键,所以我可以在点击时以文本和高清图像显示 LQ 图像。指针值不会改变,因为这一切都在一个 UITextView 中

以上是关于使用 UIImageView 作为 NSMutableDictionary 中的键来查找布尔值的主要内容,如果未能解决你的问题,请参考以下文章

使用 UIImageView 作为 NSMutableDictionary 中的键来查找布尔值

在不使用 IB 的情况下添加 UIImageView 作为 UIViewController 的子视图

PFFile 作为 UIImageView

将 UIImageView 作为参数发送到 WCF 服务

如何使用 Firebase 数据库中存储的 url 作为 UIImageView 中的图像

Swift - 通过 IBAction 将 UIImageView 作为 PNG 文件保存到图库