简体   繁体   中英

How do I compare objects in Objective-C?

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?

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

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 Foo is 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.

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

You should read the documentation for NSObject protocol and this SO question has some interesting answers on how to write your hash method.

查看isEqual:compare:方法。

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM