iOS基礎(chǔ):對(duì)于==, isEqual, hash的理解

0x00 前言

今天看到了這篇文章iOS開發(fā) 之 不要告訴我你真的懂isEqual與hash!,覺得很有意思,但是又對(duì)于里面的一部分內(nèi)容理解不了,就自己建了demo試了下然后趁熱打鐵寫篇博客記錄下。

0x01 總結(jié)

先寫下我看了這篇文章的總結(jié):

  • 1.==用于比較對(duì)象地址,如果不一致返回NO。
  • 2.isEqual用于比較對(duì)象地址,但是可以重寫,自定義判斷邏輯。
  • 3.hash不常用,在往NSSet添加對(duì)象時(shí)會(huì)用到。
  • 4.3的具體邏輯是:在add時(shí),系統(tǒng)會(huì)調(diào)用hash,如果返回值和集合里的一致,就會(huì)判斷集合內(nèi)已存在該對(duì)象,不給加。如果不一致,再調(diào)用isEqual方法判斷。
  • 如果要重寫hash,直接return [super hash]是不對(duì)的。因?yàn)榉祷氐氖菍?duì)象地址。這樣會(huì)導(dǎo)致兩個(gè)不同的對(duì)象永遠(yuǎn)加入不到同一個(gè)set里面。

0x02 例子

下面是一些測(cè)試?yán)?,我?chuàng)建了Person類,有name屬性,我會(huì)重寫isEqualhash方法來測(cè)試。

1.==isEqual方法,isEqual未重寫

    Person *person1 = [[Person alloc] init];
    person1.name = @"1";
    
    Person *person2 = [[Person alloc] init];
    person2.name = @"1";
    
    NSLog(@"%d", person1==person1);
    NSLog(@"%d", person1==person2);
    NSLog(@"%d", [person1 isEqual:person1]);
    NSLog(@"%d", [person1 isEqual:person2]);

2020-03-07 14:06:48.004179+0800 AnimateDemo[43855:5522556] 1
2020-03-07 14:06:48.004259+0800 AnimateDemo[43855:5522556] 0
2020-03-07 14:06:48.004322+0800 AnimateDemo[43855:5522556] 1
2020-03-07 14:06:48.004391+0800 AnimateDemo[43855:5522556] 0

2.==isEqual方法,isEqual重寫

- (BOOL)isEqual:(id)object {
    if (self == object) {
        return YES;
    }
    
    if (![object isKindOfClass:[Person class]]) {
        return NO;
    }
    
    if ([((Person *)object).name isEqualToString:self.name]) {
        return YES;
    } else {
        return NO;
    }
}

    Person *person1 = [[Person alloc] init];
    person1.name = @"1";
    
    Person *person2 = [[Person alloc] init];
    person2.name = @"1";
    
    NSLog(@"%d", person1==person1);
    NSLog(@"%d", person1==person2);
    NSLog(@"%d", [person1 isEqual:person1]);
    NSLog(@"%d", [person1 isEqual:person2]);

2020-03-07 14:23:33.606430+0800 AnimateDemo[43916:5530391] 1
2020-03-07 14:23:33.606498+0800 AnimateDemo[43916:5530391] 0
2020-03-07 14:23:33.606567+0800 AnimateDemo[43916:5530391] 1
2020-03-07 14:23:33.606639+0800 AnimateDemo[43916:5530391] 1

3.默認(rèn)hash調(diào)用

我重寫了hash的方法,然后NSSet里加對(duì)象

- (NSUInteger)hash {
    NSUInteger superHash = [super hash];
    NSLog(@"%ld", superHash);
    return superHash;
}

    Person *person1 = [[Person alloc] init];
    person1.name = @"1";
    
    Person *person2 = [[Person alloc] init];
    person2.name = @"1";
    
    NSMutableSet *set = [NSMutableSet set];
    [set addObject:person1];
    [set addObject:person2];
    NSLog(@"set count = %ld", set.count);

2020-03-07 14:28:55.113639+0800 AnimateDemo[43956:5534222] 105553148183088
2020-03-07 14:28:55.113703+0800 AnimateDemo[43956:5534222] 105553148183104
2020-03-07 14:28:55.113764+0800 AnimateDemo[43956:5534222] set count = 2

說明hash方法被調(diào)用了。
但是如果我不想將兩個(gè)我認(rèn)為一樣的對(duì)象加入到set里面怎么辦呢?比如例子中的兩個(gè)person對(duì)象,我認(rèn)為他們是一樣的。
那么,重寫hash并返回[super hash]是做不到的。因?yàn)椴煌瑢?duì)象的[super hash]返回的都不相同。
那么要怎么做呢?

4.正確的hash重寫方法

- (NSUInteger)hash {
    NSUInteger nameHash = self.name.hash;
    NSLog(@"%ld", nameHash);
    return nameHash;
}

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

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

    if ([((Person *)object).name isEqualToString:self.name]) {
        return YES;
    } else {
        return NO;
    }
}

    Person *person1 = [[Person alloc] init];
    person1.name = @"1";
    
    Person *person2 = [[Person alloc] init];
    person2.name = @"1";
    
    NSMutableSet *set = [NSMutableSet set];
    [set addObject:person1];
    [set addObject:person2];
    NSLog(@"set count = %ld", set.count);

2020-03-07 14:39:05.182269+0800 AnimateDemo[44016:5540023] 918
2020-03-07 14:39:05.182339+0800 AnimateDemo[44016:5540023] 918
2020-03-07 14:39:05.182412+0800 AnimateDemo[44016:5540023] set count = 1

正確的方法是用return self.name.hash;。
但是光有hash還不夠,還需要重寫isEqual方法。原因上面已經(jīng)說了,set addObject方法會(huì)先去比較hash,在去比較isEqual。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容