IOSAD-92 [NSObject isEqualToObject:basedOnKeys] IOSAD-92
authorDirk Zimmermann <dirk@pep-project.org>
Tue, 24 Apr 2018 13:29:17 +0200
branchIOSAD-92
changeset 59295dde8be4786
parent 591 6f43608139c8
child 593 78a14e6e06d0
IOSAD-92 [NSObject isEqualToObject:basedOnKeys]
pEpObjCAdapter.xcodeproj/project.pbxproj
pEpObjCAdapter/NSObject+Extension.h
pEpObjCAdapter/NSObject+Extension.m
pEpObjCAdapter/PEPMessage.m
     1.1 --- a/pEpObjCAdapter.xcodeproj/project.pbxproj	Tue Apr 24 13:29:16 2018 +0200
     1.2 +++ b/pEpObjCAdapter.xcodeproj/project.pbxproj	Tue Apr 24 13:29:17 2018 +0200
     1.3 @@ -35,6 +35,7 @@
     1.4  		435665CC2080A6CB00EC5B10 /* NSNumber+PEPRating.m in Sources */ = {isa = PBXBuildFile; fileRef = 435665CB2080A6CB00EC5B10 /* NSNumber+PEPRating.m */; };
     1.5  		435796E31FB5E51A00395A9E /* PEPMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 435796E21FB5E51A00395A9E /* PEPMessage.m */; };
     1.6  		43676B661C57EA1A00233933 /* B623F674_sec.asc in Resources */ = {isa = PBXBuildFile; fileRef = 43676B641C57EA1A00233933 /* B623F674_sec.asc */; };
     1.7 +		439393E6208F375800EB1DBD /* NSObject+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 439393E5208F375800EB1DBD /* NSObject+Extension.m */; };
     1.8  		439D91A5208479EE003F6AC2 /* PEPAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = 439D91A4208479EE003F6AC2 /* PEPAttachment.m */; };
     1.9  		43D27DE61F5DA7B700795687 /* NSDictionary+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 43D27DE51F5DA7B700795687 /* NSDictionary+Extension.m */; };
    1.10  		43DED786203C25E200D45CD6 /* NSError+PEP.m in Sources */ = {isa = PBXBuildFile; fileRef = 43DED785203C25E200D45CD6 /* NSError+PEP.m */; };
    1.11 @@ -167,6 +168,8 @@
    1.12  		435796E21FB5E51A00395A9E /* PEPMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PEPMessage.m; sourceTree = "<group>"; };
    1.13  		43676B631C57EA1A00233933 /* 0xB623F674.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 0xB623F674.asc; sourceTree = "<group>"; };
    1.14  		43676B641C57EA1A00233933 /* B623F674_sec.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = B623F674_sec.asc; sourceTree = "<group>"; };
    1.15 +		439393E4208F375800EB1DBD /* NSObject+Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+Extension.h"; sourceTree = "<group>"; };
    1.16 +		439393E5208F375800EB1DBD /* NSObject+Extension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Extension.m"; sourceTree = "<group>"; };
    1.17  		439D91A3208479EE003F6AC2 /* PEPAttachment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PEPAttachment.h; sourceTree = "<group>"; };
    1.18  		439D91A4208479EE003F6AC2 /* PEPAttachment.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PEPAttachment.m; sourceTree = "<group>"; };
    1.19  		43D27DE41F5DA78700795687 /* NSDictionary+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Extension.h"; sourceTree = "<group>"; };
    1.20 @@ -315,6 +318,8 @@
    1.21  				434ED6D5207E27B8000A7590 /* PEPAutoPointer.m */,
    1.22  				435665CA2080A6CB00EC5B10 /* NSNumber+PEPRating.h */,
    1.23  				435665CB2080A6CB00EC5B10 /* NSNumber+PEPRating.m */,
    1.24 +				439393E4208F375800EB1DBD /* NSObject+Extension.h */,
    1.25 +				439393E5208F375800EB1DBD /* NSObject+Extension.m */,
    1.26  			);
    1.27  			path = pEpObjCAdapter;
    1.28  			sourceTree = "<group>";
    1.29 @@ -489,6 +494,7 @@
    1.30  				43209B3F1ECC2DB0007E7E2E /* PEPLanguage.m in Sources */,
    1.31  				434ED6D6207E27B8000A7590 /* PEPAutoPointer.m in Sources */,
    1.32  				439D91A5208479EE003F6AC2 /* PEPAttachment.m in Sources */,
    1.33 +				439393E6208F375800EB1DBD /* NSObject+Extension.m in Sources */,
    1.34  				43209B401ECC2DB4007E7E2E /* PEPMessageUtil.m in Sources */,
    1.35  				43209B3D1ECC2DA7007E7E2E /* NSArray+Extension.m in Sources */,
    1.36  				43209B3E1ECC2DAB007E7E2E /* PEPCSVScanner.m in Sources */,
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/pEpObjCAdapter/NSObject+Extension.h	Tue Apr 24 13:29:17 2018 +0200
     2.3 @@ -0,0 +1,21 @@
     2.4 +//
     2.5 +//  NSObject+Extension.h
     2.6 +//  pEpObjCAdapter
     2.7 +//
     2.8 +//  Created by Dirk Zimmermann on 24.04.18.
     2.9 +//  Copyright © 2018 p≡p. All rights reserved.
    2.10 +//
    2.11 +
    2.12 +#import <Foundation/Foundation.h>
    2.13 +
    2.14 +@interface NSObject (Extension)
    2.15 +
    2.16 +/**
    2.17 + Invokes `[value1 isEqual:value2]` between all value pairs retrieved
    2.18 + from `self` and `other`, based on the list of keys.
    2.19 + @Note `nil` is considered equal to `nil`, in contrast to [NSObject isEqual:].
    2.20 + */
    2.21 +- (BOOL)isEqualToObject:(NSObject * _Nonnull)other
    2.22 +            basedOnKeys:(NSArray<NSString *> * _Nonnull)keys;
    2.23 +
    2.24 +@end
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/pEpObjCAdapter/NSObject+Extension.m	Tue Apr 24 13:29:17 2018 +0200
     3.3 @@ -0,0 +1,31 @@
     3.4 +//
     3.5 +//  NSObject+Extension.m
     3.6 +//  pEpObjCAdapter
     3.7 +//
     3.8 +//  Created by Dirk Zimmermann on 24.04.18.
     3.9 +//  Copyright © 2018 p≡p. All rights reserved.
    3.10 +//
    3.11 +
    3.12 +#import "NSObject+Extension.h"
    3.13 +
    3.14 +@implementation NSObject (Extension)
    3.15 +
    3.16 +- (BOOL)isEqualToObject:(NSObject * _Nonnull)other
    3.17 +            basedOnKeys:(NSArray<NSString *> * _Nonnull)keys
    3.18 +{
    3.19 +    for (NSString *theKey in keys) {
    3.20 +        NSObject *objSelf = [self valueForKey:theKey];
    3.21 +        NSObject *objOther = [other valueForKey:theKey];
    3.22 +
    3.23 +        if (objSelf == nil && objOther == nil) {
    3.24 +            // considered equal, continue
    3.25 +        } else if (![objSelf isEqual:objOther]) {
    3.26 +            // NSValue, NSArray, NSString all have correctly implemented isEqual, so this works
    3.27 +            return NO;
    3.28 +        }
    3.29 +    }
    3.30 +
    3.31 +    return YES;
    3.32 +}
    3.33 +
    3.34 +@end
     4.1 --- a/pEpObjCAdapter/PEPMessage.m	Tue Apr 24 13:29:16 2018 +0200
     4.2 +++ b/pEpObjCAdapter/PEPMessage.m	Tue Apr 24 13:29:17 2018 +0200
     4.3 @@ -9,6 +9,8 @@
     4.4  #import "PEPMessage.h"
     4.5  #import "PEPIdentity.h"
     4.6  
     4.7 +#import "NSObject+Extension.h"
     4.8 +
     4.9  @implementation PEPMessage
    4.10  
    4.11  // MARK: - NSKeyValueCoding
    4.12 @@ -238,42 +240,14 @@
    4.13  
    4.14  // MARK: - Equality
    4.15  
    4.16 +/**
    4.17 + The keys that should be used to decide `isEqual` and compute the `hash`.
    4.18 + */
    4.19 +static NSArray *s_keys;
    4.20 +
    4.21  - (BOOL)isEqualToPEPMessage:(PEPMessage * _Nonnull)message
    4.22  {
    4.23 -    NSArray *keys = @[
    4.24 -                      @"attachments",
    4.25 -                      @"bcc",
    4.26 -                      @"cc",
    4.27 -                      @"direction",
    4.28 -                      @"from",
    4.29 -                      @"inReplyTo",
    4.30 -                      @"keywords",
    4.31 -                      @"longMessage",
    4.32 -                      @"longMessageFormatted",
    4.33 -                      @"messageID",
    4.34 -                      @"optionalFields",
    4.35 -                      @"receivedBy",
    4.36 -                      @"receivedDate",
    4.37 -                      @"references",
    4.38 -                      @"replyTo",
    4.39 -                      @"sentDate",
    4.40 -                      @"shortMessage",
    4.41 -                      @"to",
    4.42 -                      ];
    4.43 -
    4.44 -    for (NSString *theKey in keys) {
    4.45 -        NSObject *objSelf = [self objectForKey:theKey];
    4.46 -        NSObject *objOther = [message objectForKey:theKey];
    4.47 -
    4.48 -        if (objSelf == nil && objOther == nil) {
    4.49 -            // considered equal, continue
    4.50 -        } else if (![objSelf isEqual:objOther]) {
    4.51 -            // NSValue, NSArray, NSString all have correctly implemented isEqual, so this works
    4.52 -            return NO;
    4.53 -        }
    4.54 -    }
    4.55 -
    4.56 -    return YES;
    4.57 +    return [self isEqualToObject:message basedOnKeys:s_keys];
    4.58  }
    4.59  
    4.60  - (NSUInteger)hash
    4.61 @@ -315,4 +289,30 @@
    4.62      return [self isEqualToPEPMessage:object];
    4.63  }
    4.64  
    4.65 +// MARK: - Static Initialization
    4.66 +
    4.67 ++ (void)initialize
    4.68 +{
    4.69 +    s_keys = @[
    4.70 +               @"attachments",
    4.71 +               @"bcc",
    4.72 +               @"cc",
    4.73 +               @"direction",
    4.74 +               @"from",
    4.75 +               @"inReplyTo",
    4.76 +               @"keywords",
    4.77 +               @"longMessage",
    4.78 +               @"longMessageFormatted",
    4.79 +               @"messageID",
    4.80 +               @"optionalFields",
    4.81 +               @"receivedBy",
    4.82 +               @"receivedDate",
    4.83 +               @"references",
    4.84 +               @"replyTo",
    4.85 +               @"sentDate",
    4.86 +               @"shortMessage",
    4.87 +               @"to",
    4.88 +               ];
    4.89 +}
    4.90 +
    4.91  @end