Как сравнить объекты в Objective-C?
Как сравнить два объекта пользовательского класса? Моя идея заключалась в том, чтобы добавить дополнительный класс к классу, в котором я могу сравнить текущий объект с другим объектом того же типа.
Поэтому я могу написать свой собственный код, как сравнивается каждое поле класса.
Вот как я это сделаю. Или существуют некоторые предопределенные методы? Как "isEqualTo" класса NSString?
Ответы
Ответ 1
Указатели на -isEqual:
хороши, но если вы реализуете -isEqual:
, вы также должны реализовать -hash
таким образом, чтобы, если два объекта возвращаются YES
для -isEqual:
, они также возвратят тот же значение для -hash
. Внедрение isEqual:
без реализации -hash
приводит к некоторым очень удивительным ошибкам при использовании таких коллекций, как NSArray.
Для новых разработчиков я рекомендую не перегружать -isEqual:
. Вместо этого я рекомендую использовать тот же метод, что и NSString, и создать пользовательский -isEqualToFoo:
(где Foo
- ваш класс), пока вы не поймете влияние -isEqual:
на коллекции и не захотите этого поведения. Перегрузка -isEqual:
мощная, но ошибки, которые вы можете создать, являются тонкими. Создание собственного пользовательского компаратора во многих случаях является более безопасным и понятным.
Ответ 2
Стандартный способ - переопределить - (BOOL)isEqual:(id)anObject
и - (NSUInteger)hash
.
Вы должны прочитать документацию для протокол NSObject и this Вопрос SO некоторые интересные ответы о том, как написать хэш-метод.
Ответ 3
Посмотрите на методы isEqual:
и compare:
.
Ответ 4
У меня есть следующий объект:
#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];