How do I compare objects in Objective-C?

后端 未结 4 1736
长发绾君心
长发绾君心 2020-12-05 18:28

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 sam

相关标签:
4条回答
  • 2020-12-05 18:36

    Look at the isEqual: and the compare: method.

    0 讨论(0)
  • 2020-12-05 18:50

    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.

    0 讨论(0)
  • 2020-12-05 18:50

    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];
    
    0 讨论(0)
  • 2020-12-05 18:58

    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.

    0 讨论(0)
提交回复
热议问题