如何比较 Objective-C 中的对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/876866/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:33:50  来源:igfitidea点击:

How do I compare objects in Objective-C?

objective-c

提问by TalkingCode

How do I compare two objects of a custom class? My idea was to add an additional method to the class in which I can compare the current object with another object of the same kind.

如何比较自定义类的两个对象?我的想法是向类中添加一个额外的方法,我可以在其中将当前对象与另一个同类对象进行比较。

So I can write my own code how each field of the class is compared.

所以我可以编写自己的代码来比较类的每个字段。

This is how I would do it. Or are there some predefined methods to do that? Like "isEqualTo" of the NSString class?

这就是我要做的。或者是否有一些预定义的方法可以做到这一点?像 NSString 类的“isEqualTo”?

回答by Rob Napier

The pointers to -isEqual:are good, but if you implement -isEqual:, you absolutely mustalso implement -hashin such a way that if two objects return YESfor -isEqual:they will also return the same value for -hash. Implementing isEqual:without also implementing -hashleads to some very surprising bugs when you use Collections like NSArray.

指向的指针-isEqual:很好,但是如果你实现了-isEqual:,你绝对还必须-hash以这样一种方式实现,如果两个对象返回YESfor-isEqual:它们也将返回相同的值-hash。当您使用像 NSArray 这样的集合时,在isEqual:没有实现的情况下实现-hash会导致一些非常令人惊讶的错误。

For new developers, I tend to recommend against overloading -isEqual:. I recommend instead using the same technique as NSString, and create a custom -isEqualToFoo:(where Foois your class) until you understand the impact of -isEqual:on collections and specifically want this behavior. Overloading -isEqual:powerful, but the bugs you can create are subtle. Creating your own custom comparator is safer and clearer in many cases.

对于新开发人员,我倾向于建议不要重载-isEqual:. 我建议改为使用与 NSString 相同的技术,并创建一个自定义-isEqualToFoo:Foo您的类在哪里),直到您了解-isEqual:对集合的影响并特别想要这种行为。重载-isEqual:功能强大,但您可以创建的错误很微妙。在许多情况下,创建自己的自定义比较器更安全、更清晰。

回答by pgb

The standard way is to override - (BOOL)isEqual:(id)anObjectand - (NSUInteger)hash.

标准方法是覆盖- (BOOL)isEqual:(id)anObject- (NSUInteger)hash

You should read the documentation for NSObject protocoland thisSO question has some interesting answers on how to write your hash method.

您应该阅读NSObject 协议的文档,这个问题有一些关于如何编写哈希方法的有趣答案。

回答by Georg Sch?lly

Look at the isEqual:and the compare:method.

看方法isEqual:compare:方法。

回答by Javier Calatrava Llavería

I have the following object:

我有以下对象:

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSUInteger, SeasonType) {
    kWinter,
    kSpring,
    kSummer,
    kFall
};

@interface Season : NSObject

@property (nonatomic) SeasonType season;
@property (nonatomic) NSUInteger year;

+(id) seasonWithYear:(NSInteger)year season:(SeasonType)season;
-(id) initWithYear:(NSInteger)year season:(SeasonType)season;

@end

What I do is overwrite base NSObject comparison methods, there's no need of reinventing the wheel and code keeps cleaner as well:

我所做的是覆盖基本的 NSObject 比较方法,无需重新发明轮子,代码也保持清洁:

#import "Season.h"

@interface Season()

@end

@implementation Season

+(id) seasonWithYear:(NSInteger)year season:(SeasonType)season{
    return [[self alloc] initWithYear:year season:season];
}

-(id) initWithYear:(NSInteger)year season:(SeasonType)season{
    self = [super init];
    if (self)
    {
        _year = year;
        _season=season;
        _baseDate=nil;
    }

    return self;
}

#pragma mark - NSObject

- (BOOL)isEqual:(id)object {
    if (self == object) {
        return YES;
    }

    if (![object isKindOfClass:[Season class]]) {
        return NO;
    }

    return [self _isEqualToSeason:(Season *)object];
}

- (NSUInteger)hash {
    return self.season ^ self.year;
}


#pragma mark - Private/Internal

- (BOOL)_isEqualToSeason:(Season *)season {
    if (!season) {
        return NO;
    }

    return ((!self.season && !season.season) || self.season == season.season) &&
    ((!self.year && !season.year)    ||  self.year == season.year) ;
}

@end

Usage:

用法:

Season *season2 = [Season seasonWithYear:2010 season:kFall];
Season *season3 = [Season seasonWithYear:2009 season:kFall];
[season2 isEqual:season3];