1

I'd like to generate an MD5 hash for an NSObject:

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * type;
@property (nonatomic, retain) NSString * unit;
@property (nonatomic, retain) NSArray * fields;

What is the best way to do so? I've seen examples for hashing from a dictionary or an array, but not from an entire NSObject.

ebi
  • 4,862
  • 6
  • 29
  • 40
  • 2
    [dupe1](http://stackoverflow.com/questions/2018550/how-do-i-create-an-md5-hash-of-a-string-in-cocoa) [dupe2](http://stackoverflow.com/questions/652300/using-md5-hash-on-a-string-in-cocoa) [dupe3](http://stackoverflow.com/questions/1524604/md5-algorithm-in-objective-c) [dupe4](http://stackoverflow.com/questions/15947597/how-to-convert-nsstring-to-md5-hash-in-objective-c) don't you people even attempt to use Google or the site search! That'd be blasphemy! –  Oct 10 '13 at 20:33
  • 1
    @H2CO3 What do you mean by "you people"? And this question isn't a duplicate as it's about hashing a custom object rather than a string or an array or a dictionary. Yes it's similar, but it's worth answering. – Abizern Oct 10 '13 at 21:31
  • @Abizern OP and authors of other dupes. Still not a good enough reason to post the identical question. Or is it? –  Oct 10 '13 at 21:38
  • 1
    @H2CO3 I saw those other posts already and posted my questions since those are all asking about hashing a string, I did not find any other questions about hashing an NSObject subclass, on s.o. or through google. Next time maybe you should read a bit before jumping the gun. – ebi Oct 11 '13 at 01:39

2 Answers2

5

To generate a MD5 hash for an NSObject or a subclass of NSObject, you need to convert it into something that's easily hashable but still represents the state of the instance. A JSON string is one such option. The code looks like this:

Model.h

#import <Foundation/Foundation.h>

@interface Model : NSObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * type;
@property (nonatomic, retain) NSString * unit;
@property (nonatomic, retain) NSArray * fields;

- (NSString *)md5Hash;

@end

Model.m

#import <CommonCrypto/CommonDigest.h>
#import "Model.h"

@implementation Model

- (NSString *)md5Hash
{
    // Serialize this Model instance as a JSON string
    NSDictionary *map = @{ @"name": self.name, @"type": self.type,
                           @"unit": self.unit, @"fields": self.fields };

    NSError *error = NULL;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:map
                                                        options:NSJSONWritingPrettyPrinted
                                                          error:&error];
    if (error != nil) {
        NSLog(@"Serialization Error: %@", error);
        return nil;
    }

    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

    // Now create the MD5 hashs
    const char *ptr = [jsonString UTF8String];
    unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];

    CC_MD5(ptr, strlen(ptr), md5Buffer);

    NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
        [output appendFormat:@"%02x",md5Buffer[i]];

    return output;
}

@end

Then you can easily retrieve the MD5 hash just by calling the md5Hash method

Model *obj = [Model new];
obj.name = @"...";
obj.type = @"...";
obj.unit = @"...";
obj.fields = @[ ... ];

NSString *hashValue = [obj md5Hash];
neilco
  • 7,964
  • 2
  • 36
  • 41
  • Is there any way to do this with nested objects? I tried doing this with my objects, but they all have object properties: property (nonatomic, retain) NSString * name; property (nonatomic, retain) MyRelatedObject * related; – ebi Oct 11 '13 at 04:48
0

You can convert the object into a dictionary if you already have code for creating the hash:

NSDictionary *dict = [myObject dictionaryWithValuesForKeys:@[@"name", @"type", @"unit", @"fields"]];

Or you could implement <NSCoding> on your class, archive it and hash the resulting data.

Wain
  • 118,658
  • 15
  • 128
  • 151