iOS 如何比较对象是否相等?

iOS How do I compare if Objects are Equal?

我有一个从 Web 服务中提取的对象列表。当我更新我的 UITableView 时,我再次从 Web 服务中检索对象,并将它们相互比较是否相等。然后我删除那些不存在的对象,插入新对象,然后更新我的 UITableView。我如何测试新对象是否等于旧对象?为了清楚起见,我创建了一个测试..

requestA 应该等于 requestC,但失败了。

这是否可以在不查看每个 属性 值的情况下完成,因为对象有很多值?

我最初只比较 ID,但这不起作用,因为有时其他 属性 值发生变化而 ID 保持不变。

    Request *requestA = [[Request alloc] init];
    Request *requestB = [[Request alloc] init];
    Request *requestC = [[Request alloc] init];

    requestA.requestID = @"1";
    requestA.productName = @"Clutch";
    requestB.requestID = @"2";
    requestB.productName = @"Wiper";
    requestC.requestID = @"1";
    requestC.productName = @"Clutch";

    if (requestA == requestB)
        NSLog(@"A == B");

    if (requestA == requestC)
        NSLog(@"A == C");

    if ([requestA isEqual:requestB])
        NSLog(@"A isEqual B");

    if ([requestA isEqual:requestC])
        NSLog(@"A isEqual C");

    // Look at the pointers:
    NSLog(@"%p", requestA);
    NSLog(@"%p", requestB);
    NSLog(@"%p", requestC);

检查这个答案:How do I compare objects in Objective-C?

您需要为 Request class 实施 -isEqual:-hash 方法。

您需要覆盖 isEqual: 请求对象以指定要比较的属性。 写……像这样:

- (BOOL)isEqual:(id)other {
    if (other == self) return YES;
    if (!other || ![other isKindOfClass:[self class]]) return NO;
    if (![(id)[self name] isEqual:[other name]]) return NO;
    // add other checks if needed
    return YES;
}

首先。 == 是对 "are these two objects actually the SAME OBJECT" 的检查。 IE。它们只是指向相同但内存的两个指针。

您需要使用 isEqual 方法。但是,为了正确执行此操作,您需要重写 class.

中的方法

类似...

- (BOOL)isEqual:(Request *)otherObject
{
    return [self.productName isEqual:otherObject.productName]
    && [self.requestID isEqual:otherObject.requestID];
}

isEqual: 是在 NSObject Protocol 中声明的方法。来自isEqual的官方文档:

This method defines what it means for instances to be equal. For example, a container object might define two containers as equal if their corresponding objects all respond YES to an isEqual: request. See the NSData, NSDictionary, NSArray, and NSString class specifications for examples of the use of this method.

If two objects are equal, they must have the same hash value. This last point is particularly important if you define isEqual: in a subclass and intend to put instances of that subclass into a collection. Make sure you also define hash in your subclass.

因此,正如 Salavat Khanov 在他的回答中指出的那样:

You need to implement -isEqual: and -hash methods for your Request class.

您想做这样的事情:

// TestRequest.h
@interface TestRequest : NSObject

@property (nonatomic) NSString *requestID;
@property (nonatomic) NSString *productName;

@end

// TestRequest.m
#import "TestRequest.h"

@implementation TestRequest
- (BOOL)isEqual:(TestRequest *)object {
    if (self == object) {
        return YES;
    }

    if (![self.requestID isEqual:object.requestID]) {
        return NO;
    }

    if (![self.productName isEqual:object.productName]) {
        return NO;
    }

    return YES;
}

- (NSUInteger)hash {
    // this is a very simple hash function
    return [self.requestID hash] ^ [self.productName hash];
}
@end

或者您可以使用自定义方法:

- (BOOL)isEqualToRequest:(TestRequest *)otherRequest {
    return [self.requestID isEqualToString:otherRequest.requestID] && 
           [self.productName isEqualToString:otherRequest.productName];
}