Objective-C:使用自定义对象键从 NSMutableDictionary 获取值

发布于 2024-12-05 14:00:17 字数 1082 浏览 0 评论 0 原文

我一直使用 NSDictionaries 以字符串作为键,以及网络/书籍/等上的几乎所有示例。是一样的。我想我应该尝试使用自定义对象作为密钥。我已经阅读了有关实现“copyWithZone”方法的信息,并创建了以下基本类:

@interface CustomClass : NSObject
{
    NSString *constString;
}

@property (nonatomic, strong, readonly) NSString *constString;

- (id)copyWithZone:(NSZone *)zone; 

@end

@implementation CustomClass

@synthesize constString;

- (id)init
{
    self = [super init];
    if (self) {
        constString = @"THIS IS A STRING";
    }
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    CustomClass *copy = [[[self class] allocWithZone: zone] init];
    return copy;
}

@end

现在我尝试仅添加带有简单字符串值的这些对象之一,然后将字符串值返回以登录到控制台:

CustomClass *newObject = [[CustomClass alloc] init];
NSString *valueString = @"Test string";
NSMutableDictionary *dict =
[[NSMutableDictionary alloc] initWithObjectsAndKeys:valueString, newObject, nil];

    NSLog(@"Value in Dictionary: %@", [dict objectForKey: newObject]);
    // Should output "Value in Dictionary: Test string"

不幸的是日志显示(空)。我很确定我错过了一些非常明显的东西,并且感觉我需要另一双眼睛。

I've always used NSDictionaries with strings as keys, and pretty much all the examples on the web/books/etc. are the same. I figured that I'd try it with a custom object for a key. I've read up on implementing the "copyWithZone" method and created the following basic class:

@interface CustomClass : NSObject
{
    NSString *constString;
}

@property (nonatomic, strong, readonly) NSString *constString;

- (id)copyWithZone:(NSZone *)zone; 

@end

@implementation CustomClass

@synthesize constString;

- (id)init
{
    self = [super init];
    if (self) {
        constString = @"THIS IS A STRING";
    }
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    CustomClass *copy = [[[self class] allocWithZone: zone] init];
    return copy;
}

@end

Now I'm trying to just add one of these objects with a simple string value, and then getting the string value back out to log to the console:

CustomClass *newObject = [[CustomClass alloc] init];
NSString *valueString = @"Test string";
NSMutableDictionary *dict =
[[NSMutableDictionary alloc] initWithObjectsAndKeys:valueString, newObject, nil];

    NSLog(@"Value in Dictionary: %@", [dict objectForKey: newObject]);
    // Should output "Value in Dictionary: Test string"

Unfortunately the log displays a (null). I'm pretty sure I'm missing something really obvious, and feel like I need another set of eyes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

满意归宿 2024-12-12 14:00:18

NSDictionary key 对象使用三种方法:

  • -(NSUInteger)hash
  • -(BOOL)isEqual:(id)other
  • -(id )copyWithZone:(NSZone*)zone

hashisEqual: 的默认 NSObject 实现仅使用对象的指针,因此当你的对象通过copyWithZone复制:副本和原始对象不再相等。

您需要的是这样的:

@implementation CustomClass

-(NSUInteger) hash;
{
    return [constString hash];
}

-(BOOL) isEqual:(id)other;
{
    if([other isKindOfClass:[CustomClass class]])
        return [constString isEqualToString:((CustomClass*)other)->constString];
    else
        return NO;
}
- (id)copyWithZone:(NSZone *)zone
{
    CustomClass *copy = [[[self class] allocWithZone: zone] init];
    copy->constString = constString; //might want to copy or retain here, just incase the string isn't a constant
    return copy;
}

@end

从文档中找到这一点有点困难。 NSDictionary 概述 告诉您有关 isEqual:NS复制

在字典中,键是唯一的。也就是说,一个键中没有两个键
单个字典相等(由 isEqual: 确定)。一般来说,一个
key 可以是任何对象(前提是它符合 NSCopying
协议 - 见下文),但请注意,当使用键值编码时,键
必须是字符串(请参阅“键值编码基础知识”)。

如果您查看 -[NSObject isEqual:] 的文档它告诉关于哈希

如果两个对象相等,则它们必须具有相同的哈希值。这
如果您在 a 中定义 isEqual: ,那么最后一点尤其重要
子类并打算将该子类的实例放入
收藏。确保您还在子类中定义了哈希。

NSDictionary key objects work off three methods:

  • -(NSUInteger)hash
  • -(BOOL)isEqual:(id)other
  • -(id)copyWithZone:(NSZone*)zone

The default NSObject implementation of hash and isEqual: only use the object's pointer, so when your object is copied via copyWithZone: the copy and the original object are no longer equal.

What you need is something like this:

@implementation CustomClass

-(NSUInteger) hash;
{
    return [constString hash];
}

-(BOOL) isEqual:(id)other;
{
    if([other isKindOfClass:[CustomClass class]])
        return [constString isEqualToString:((CustomClass*)other)->constString];
    else
        return NO;
}
- (id)copyWithZone:(NSZone *)zone
{
    CustomClass *copy = [[[self class] allocWithZone: zone] init];
    copy->constString = constString; //might want to copy or retain here, just incase the string isn't a constant
    return copy;
}

@end

It's a little bit difficult to find this out from the documentation. The overview for NSDictionary tells you about isEqual: and NSCopying:

Within a dictionary, the keys are unique. That is, no two keys in a
single dictionary are equal (as determined by isEqual:). In general, a
key can be any object (provided that it conforms to the NSCopying
protocol—see below), but note that when using key-value coding the key
must be a string (see “Key-Value Coding Fundamentals”).

And if you have a look at the documentation for -[NSObject isEqual:] it tells you about hash:

If two objects are equal, they must have the same hash value. This
last point is particularly important if you define isEqual: in a
subclass and intend to put instances of that subclass into a
collection. Make sure you also define hash in your subclass.

橘味果▽酱 2024-12-12 14:00:18

我认为你的类需要定义:

- (BOOL)isEqual:(id)anObject

这就是字典可能使用的来确定你的键是否等于字典中已使用的键。

I think your class needs to define:

- (BOOL)isEqual:(id)anObject

That is what is probably used by the dictionary to determine if your key is equal to one already used in the dictionary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文