iOS 判斷對象是否相等的方法

===: 比較兩個對象的內存地址

isEqualToString: 比較兩個字符串的內容

isEqual: 默認狀況下是比較兩個對象的內存地址, 可是有一些系統自帶的類(好比Foundation中的NSString, NSArray等)重寫了這個方法, 改變了這個方法的判斷規則(通常改成比較兩個對象的內容, 不是內存地址);
例如:數組NSArray中的containsObject:, indexOfObject: 方法就是利用isEqual來比較的, 因此數組中的字符串內容若是同樣的話, 也會被認爲是同樣的;

複製代碼
- (void)test1 {
    NSString *string1 = @"jack";
    NSString *string2 = [NSString stringWithFormat:@"jack"];
    
    //理論是來講,這兩個字符串存儲在內存的不一樣區域, 爲不一樣的對象, 可是系統重寫後改爲了比較內容
    NSLog(@"string1 -- %p\nstring2 --- %p",string1, string2);
    
    //比較這兩個對象的內存地址是否相等
    if (string1 == string2) {
        NSLog(@"string1 == string2");
    }
    else {
        NSLog(@"string1 != string2");
    }
    
    //比較這兩個對象的內容是否相等
    if ([string1 isEqualToString:string2]) {
        NSLog(@"string1 is equal to string2");
    }
    else {
        NSLog(@"string1 is not equal to string2");
    }
    
    //比較這兩個對象的內容是否相等
    if ([string1 isEqual:string2]) {
        NSLog(@"string1 is equal string2");
    }
    else {
        NSLog(@"string1 is not equal string2");
    }
}

輸出內容:
string1 -- 0x10aab4ef0
string2 --- 0x8843f2a833eb3556
string1 != string2
string1 is equal to string2
string1 is equal string2
複製代碼


下面兩個數組並非同一個,可是內容相同, 所以會被斷定爲相同數組

- (void)test2 {
    NSString *string1 = [NSString stringWithFormat:@"111"];
    NSString *string2 = [NSString stringWithFormat:@"222"];
    
    //兩個存儲不一樣對象的數組, 但內容是相同的
    NSArray *array1 = @[string1, @"222", @"333"];
    NSArray *array2 = @[@"111", string2, @"333"];
    
    //數組內容相同
    NSLog(@"array1 --- %@",array1);
    NSLog(@"array2 --- %@",array2);

    //數組內存地址不一樣
    NSLog(@"array1 --- %p",array1);
    NSLog(@"array2 --- %p",array2);

    NSArray *array = @[array1, array2];
    
    //輸出結果爲0, 由於array1 與 array2 是同樣的
    NSLog(@"index --- %zd",[array indexOfObject:array2]);
}

輸出結果:
array1 --- (
    111,
    222,
    333
)
array2 --- (
    111,
    222,
    333
)
array1 --- 0x6000014813e0
array2 --- 0x600001481410
index --- 0
複製代碼


若是有兩個內容相同的MYPerson對象, 則會被認爲是不一樣的, 由於此時是對內存地址進行比較, 看是否是同一個對象;bash

//沒有重寫isEqual:以前
- (void)test3 {
    MYPerson *p1 = [[MYPerson alloc] init];
    p1.age = 20;
    p1.no = 30;
    
    MYPerson *p2 = [[MYPerson alloc] init];
    p2.age = 20;
    p2.no = 30;
    
    //兩個對象的內存地址
    NSLog(@"p1 --- %p",p1);
    NSLog(@"p2 --- %p",p2);
    
    if (p1 == p2) {
        NSLog(@"p1 == p2");
    }
    else {
        NSLog(@"p1 != p2");
    }
    
    if ([p1 isEqual:p2]) {
        NSLog(@"p1 is equal p2");
    }
    else {
        NSLog(@"p1 is not equal p2");
    }
}

輸出結果:
p1 --- 0x600000381aa0
p2 --- 0x600000381ad0
p1 != p2
p1 is not equal p2
複製代碼
MYPerson.h文件
#import <Foundation/Foundation.h>
#import "MYCar.h"
NS_ASSUME_NONNULL_BEGIN

@interface MYPerson : NSObject
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, assign) NSInteger no;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) MYCar *car;

- (BOOL)isEqualToPerson:(MYPerson *)person;
@end

MYPerson.m文件
#import "MYPerson.h"

@implementation MYPerson
- (NSUInteger)hash {
    return self.age + self.no + self.name.hash + self.car.hash;
}

- (BOOL)isEqual:(id)object {
    return [self isEqualToPerson:object];
}

- (BOOL)isEqualToPerson:(MYPerson *)person {
    //若是是徹底相同的對象, 就省去後面的判斷
    if (self == person) return YES;
    //若是object的類型不對, 就不須要比較
    if (![person isKindOfClass:self.class]) return NO;
    //基本數據類型
    BOOL result = (self.age == person.age && self.no == person.no);
    if (result == NO) return result;
    
    //對象類型, 兩個對象爲nil時, isEqual的結果爲0(NO), 因此須要專門處理
    if (self.name || person.name) {
        if (![self.name isEqual:person.name]) return NO;
    }
    if (self.car || person.car) {
        if (![self.car isEqual:person.car]) return NO;
    }
    return YES;
}
@end

複製代碼


若是但願MYPerson也能像系統的類NSString同樣, 可以對內容相同的兩個不一樣對象也認定爲相同, 須要重寫isEqual方法:ui

//重寫isEqual: 以後
- (void)test3 {
    MYPerson *p1 = [[MYPerson alloc] init];
    p1.age = 20;
    p1.no = 30;
    
    MYPerson *p2 = [[MYPerson alloc] init];
    p2.age = 20;
    p2.no = 30;
    
    //兩個對象的內存地址
    NSLog(@"p1 --- %p",p1);
    NSLog(@"p2 --- %p",p2);
    
    //內存地址不一樣
    if (p1 == p2) {
        NSLog(@"p1 == p2");
    }
    else {
        NSLog(@"p1 != p2");
    }
    
    //內容相同
    if ([p1 isEqual:p2]) {
        NSLog(@"p1 is equal p2");
    }
    else {
        NSLog(@"p1 is not equal p2");
    }
}
複製代碼

  MYPerson中重寫的代碼以下:atom

MYPerson.h文件
#import <Foundation/Foundation.h>
#import "MYCar.h"
NS_ASSUME_NONNULL_BEGIN

@interface MYPerson : NSObject
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, assign) NSInteger no;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) MYCar *car;

- (BOOL)isEqualToPerson:(MYPerson *)person;
@end

NS_ASSUME_NONNULL_END



MYPerson.m文件
#import "MYPerson.h"
/*
一旦重寫了isEqual:方法, 最好重寫hash方法, 並且要遵照如下原則:
1: isEqual: 返回YES的2個對象, hash值必定要同樣
2: hash 值同樣的2個對象, isEqual: 返回不必定是YES
*/

@implementation MYPerson
- (NSUInteger)hash {
    return self.age + self.no + self.name.hash + self.car.hash;
}

- (BOOL)isEqual:(id)object {
    return [self isEqualToPerson:object];
}

- (BOOL)isEqualToPerson:(MYPerson *)person {
    //若是是徹底相同的對象, 就省去後面的判斷
    if (self == person) return YES;
    
    //若是object的類型不對, 就不須要比較
    if (![person isKindOfClass:self.class]) return NO;
    
    //基本數據類型
    BOOL result = (self.age == person.age && self.no == person.no);
    if (result == NO) return result;
    
    //對象類型, 兩個對象爲nil時, isEqual的結果爲0(NO), 因此須要專門處理
    if (self.name || person.name) {
        if (![self.name isEqual:person.name]) return NO;
    }
    if (self.car || person.car) {
        if (![self.car isEqual:person.car]) return NO;
    }
    return YES;
}
@end
複製代碼


原文: blog.csdn.net/qq_23892379…spa

相關文章
相關標籤/搜索