使用 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
中的键必须符合 NSCopying
而UIImageView
则不然。
您必须找到不同的密钥,或者您可以扩展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 的子视图