Created
March 6, 2013 11:52
-
-
Save beccadax/5098807 to your computer and use it in GitHub Desktop.
Property list serialization protocol/category. This allows you to easily make an NSObject subclass generate a plist version of itself, or initialize itself from a plist. Simply conform to the TsPropertyListRepresentation protocol and call the +includeKeyInPropertyListRepresentation:... methods at an appropriate time, such as an +initialize metho…
This file contains hidden or 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
// | |
// NSObject+TsPropertyListRepresentation.h | |
// PressKit | |
// | |
// Created by Brent Royal-Gordon on 3/6/13. | |
// Copyright (c) 2013 Novelty Publishers. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
@protocol TsPropertyListRepresentation <NSObject> | |
// These all automatically become available to NSObject subclasses which conform to this protocol. | |
@optional | |
- (id)initWithPropertyListRepresentation:(NSDictionary*)rep; | |
@property (readonly) NSDictionary* propertyListRepresentation; | |
- (instancetype)willInitWithPropertyListRepresentation:(NSDictionary*)rep; | |
- (instancetype)didInitWithPropertyListRepresentation:(NSDictionary*)rep; | |
// Call these from a +initialize method | |
+ (void)includeKeyInPropertyListRepresentation:(NSString*)key; | |
+ (void)includeKeyInPropertyListRepresentation:(NSString*)key withValueTransformer:(NSValueTransformer*)transformer; | |
+ (void)includeKeyInPropertyListRepresentation:(NSString*)key withValueTransformer:(NSValueTransformer*)transformer propertyListKey:(NSString*)plistKey; | |
@end |
This file contains hidden or 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
// | |
// NSObject+TsPropertyListRepresentation.m | |
// PressKit | |
// | |
// Created by Brent Royal-Gordon on 3/6/13. | |
// Copyright (c) 2013 Novelty Publishers. All rights reserved. | |
// | |
#import "NSObject+TsPropertyListRepresentation.h" | |
#import <objc/runtime.h> | |
@interface TsNoOpValueTransformer : NSValueTransformer @end | |
@implementation NSObject (TsPropertyListRepresentation) | |
+ (NSMutableDictionary*)ts_propertyListRepresentationKeysForThisClassOnly { | |
NSMutableDictionary * dict = objc_getAssociatedObject(self, _cmd); | |
if(!dict) { | |
dict = [NSMutableDictionary new]; | |
objc_setAssociatedObject(self, _cmd, dict, OBJC_ASSOCIATION_RETAIN_NONATOMIC); | |
} | |
return dict; | |
} | |
+ (NSDictionary*)ts_propertyListRepresentationKeys { | |
NSMutableDictionary * dict = ([self.superclass ts_propertyListRepresentationKeys] ?: @{}).mutableCopy; | |
[dict addEntriesFromDictionary:[self ts_propertyListRepresentationKeysForThisClassOnly]]; | |
return dict; | |
} | |
+ (void)includeKeyInPropertyListRepresentation:(NSString*)key withValueTransformer:(NSValueTransformer*)transformer propertyListKey:(NSString *)plistKey { | |
if(![self conformsToProtocol:@protocol(TsPropertyListRepresentation)]) { | |
[self doesNotRecognizeSelector:_cmd]; | |
} | |
[self ts_propertyListRepresentationKeysForThisClassOnly][key] = @{ @"plistKey": plistKey, NSValueTransformerBindingOption: transformer ?: [TsNoOpValueTransformer new] }; | |
} | |
+ (void)includeKeyInPropertyListRepresentation:(NSString*)key withValueTransformer:(NSValueTransformer *)transformer { | |
[self includeKeyInPropertyListRepresentation:key withValueTransformer:transformer propertyListKey:key]; | |
} | |
+ (void)includeKeyInPropertyListRepresentation:(NSString*)key { | |
[self includeKeyInPropertyListRepresentation:key withValueTransformer:nil]; | |
} | |
- (id)initWithPropertyListRepresentation:(NSDictionary*)plist { | |
if(![self conformsToProtocol:@protocol(TsPropertyListRepresentation)]) { | |
[self doesNotRecognizeSelector:_cmd]; | |
return nil; | |
} | |
if((self = [self init])) { | |
self = [self willInitWithPropertyListRepresentation:plist]; | |
for(NSString * key in [self.class ts_propertyListRepresentationKeys]) { | |
NSDictionary * info = [self.class ts_propertyListRepresentationKeys][key]; | |
id value = plist[info[@"plistKey"]]; | |
if(!value) { | |
continue; | |
} | |
value = [info[NSValueTransformerBindingOption] reverseTransformedValue:value]; | |
[self setValue:value forKey:key]; | |
} | |
self = [self didInitWithPropertyListRepresentation:plist]; | |
} | |
return self; | |
} | |
- (instancetype)willInitWithPropertyListRepresentation:(NSDictionary*)rep { return self; } | |
- (instancetype)didInitWithPropertyListRepresentation:(NSDictionary*)rep { return self; } | |
- (NSDictionary*)propertyListRepresentation { | |
if(![self conformsToProtocol:@protocol(TsPropertyListRepresentation)]) { | |
[self doesNotRecognizeSelector:_cmd]; | |
return nil; | |
} | |
NSMutableDictionary * plist = [NSMutableDictionary new]; | |
for(NSString * key in [self.class ts_propertyListRepresentationKeys]) { | |
NSDictionary * info = [self.class ts_propertyListRepresentationKeys][key]; | |
id value = [self valueForKey:key]; | |
value = [info[NSValueTransformerBindingOption] transformedValue:value]; | |
if(!value) { | |
continue; | |
} | |
plist[info[@"plistKey"]] = value; | |
} | |
return plist.copy; | |
} | |
@end | |
@implementation TsNoOpValueTransformer | |
+ (BOOL)allowsReverseTransformation { | |
return YES; | |
} | |
- (id)transformedValue:(id)value { | |
return value; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment