Last active
December 27, 2015 06:09
-
-
Save jeremytregunna/7279371 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NudgeModel.h | |
// NudgeFoundation | |
// | |
// Created by Jeremy Tregunna on 10/7/2013. | |
// Copyright (c) 2013 Jeremy Tregunna. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
#define weakify(o) try {} @finally {} \ | |
__weak typeof(o) nf_weak_ ## o = o | |
#define strongify(o) try {} @finally {} \ | |
_Pragma("clang diagnostic push") \ | |
_Pragma("clang diagnostic ignored \"-Wshadow\"") \ | |
typeof(nf_weak_ ## o) o = nf_weak_ ## o \ | |
_Pragma("clang diagnostic pop") | |
@interface NudgeModel : NSObject <NSSecureCoding, NSCopying, NSFastEnumeration> | |
- (instancetype)initWithAttributes:(NSDictionary*)attributes; | |
// Override this method and return a dictionary whose keys are the | |
// property name you define, and whose values are their key path to | |
// some external dictionary supplied during initialization. | |
- (NSDictionary*)keyPathsByPropertyKey; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NudgeModel.m | |
// NudgeFoundation | |
// | |
// Created by Jeremy Tregunna on 10/7/2013. | |
// Copyright (c) 2013 Jeremy Tregunna. All rights reserved. | |
// | |
#import "NudgeModel.h" | |
#import <objc/runtime.h> | |
@implementation NudgeModel | |
- (instancetype)initWithAttributes:(NSDictionary*)attributes | |
{ | |
if((self = [super init])) | |
{ | |
@weakify(self); | |
[[self keyPathsByPropertyKey] enumerateKeysAndObjectsUsingBlock:^(id key, NSString* keyPath, BOOL *stop) { | |
@strongify(self); | |
id object = [attributes valueForKeyPath:keyPath]; | |
if(object != nil) | |
[self setValue:object forKey:key]; | |
}]; | |
} | |
return self; | |
} | |
#pragma mark - NSCoding | |
+ (BOOL)supportsSecureCoding | |
{ | |
return YES; | |
} | |
- (id)initWithCoder:(NSCoder*)decoder | |
{ | |
if((self = [super init])) | |
{ | |
[[self keyPathsByPropertyKey] enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { | |
id object = [decoder decodeObjectForKey:key]; | |
[self setValue:object forKey:key]; | |
}]; | |
} | |
return self; | |
} | |
- (void)encodeWithCoder:(NSCoder*)coder | |
{ | |
[[self keyPathsByPropertyKey] enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { | |
id object = [self valueForKey:key]; | |
if(object != nil) | |
[coder encodeObject:object forKey:key]; | |
}]; | |
} | |
#pragma mark - NSCopying | |
- (id)copyWithZone:(NSZone*)zone | |
{ | |
typeof(self) obj = [[[self class] alloc] init]; | |
@weakify(self); | |
[[self keyPathsByPropertyKey] enumerateKeysAndObjectsUsingBlock:^(id key, NSString* keyPath, BOOL *stop) { | |
@strongify(self); | |
id o = [self valueForKey:key]; | |
[obj setValue:o forKey:key]; | |
}]; | |
return obj; | |
} | |
#pragma mark - NSFastEnumeration | |
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state objects:(__unsafe_unretained id[])buffer count:(NSUInteger)len | |
{ | |
return [[[self keyPathsByPropertyKey] allKeys] countByEnumeratingWithState:state objects:buffer count:len]; | |
} | |
#pragma mark - NSObject | |
- (BOOL)isEqual:(NudgeModel*)model | |
{ | |
if(self == model) | |
return YES; | |
if(![model isMemberOfClass:[self class]]) | |
return NO; | |
__block BOOL result = YES; | |
@weakify(self); | |
[[self keyPathsByPropertyKey] enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { | |
@strongify(self); | |
id o1 = [self valueForKey:key]; | |
id o2 = [model valueForKey:key]; | |
result = ((o1 == nil && o2 == nil) || [o1 isEqual:o2]); | |
if(!result) | |
*stop = YES; | |
}]; | |
return result; | |
} | |
- (NSUInteger)hash | |
{ | |
__block NSUInteger hash = 0; | |
@weakify(self); | |
[[self keyPathsByPropertyKey] enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { | |
@strongify(self); | |
hash ^= [[self valueForKey:key] hash]; | |
}]; | |
return hash; | |
} | |
#pragma mark - Key paths | |
- (NSDictionary*)keyPathsByPropertyKey | |
{ | |
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)] userInfo:nil]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment