Как мне сравнить объекты в Objective-C? - PullRequest
23 голосов
/ 18 мая 2009

Как сравнить два объекта пользовательского класса? Моя идея состояла в том, чтобы добавить в класс дополнительный метод, в котором я могу сравнить текущий объект с другим объектом того же вида.

Таким образом, я могу написать свой собственный код для сравнения каждого поля класса.

Вот как бы я это сделал. Или есть какие-то предопределенные методы для этого? Как "isEqualTo" класса NSString?

Ответы [ 4 ]

54 голосов
/ 18 мая 2009

Указатели на -isEqual: хороши, но если вы реализуете -isEqual:, вы абсолютно должны также реализовать -hash так, что если два объекта возвращают YES для -isEqual: они также вернут то же значение для -hash. Реализация isEqual: без реализации -hash приводит к некоторым очень удивительным ошибкам при использовании коллекций, таких как NSArray.

Для новых разработчиков я склонен рекомендовать против перегрузки -isEqual:. Вместо этого я рекомендую использовать ту же технику, что и NSString, и создавать пользовательский -isEqualToFoo: (где Foo - ваш класс), пока вы не поймете влияние -isEqual: на коллекции и не захотите этого поведения. Перегрузка -isEqual: мощная, но ошибки, которые вы можете создать, неуловимы. Создание собственного пользовательского компаратора во многих случаях безопаснее и понятнее.

6 голосов
/ 18 мая 2009

Стандартный способ - переопределить - (BOOL)isEqual:(id)anObject и - (NSUInteger)hash.

Вы должны прочитать документацию для протокола NSObject и на этот SO вопрос имеет несколько интересных ответов о том, как написать свой хэш-метод.

1 голос
/ 18 мая 2009

Посмотрите на isEqual: и compare: метод.

0 голосов
/ 11 июня 2016

У меня есть следующий объект:

#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

Что я делаю, так это перезаписываю базовые методы сравнения 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

Использование:

Season *season2 = [Season seasonWithYear:2010 season:kFall];
Season *season3 = [Season seasonWithYear:2009 season:kFall];
[season2 isEqual:season3];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...