NSValueTransformer+MTLPredefinedTransformerAdditions.m
4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//
// NSValueTransformer+MTLPredefinedTransformerAdditions.m
// Mantle
//
// Created by Justin Spahr-Summers on 2012-09-27.
// Copyright (c) 2012 GitHub. All rights reserved.
//
#import "NSValueTransformer+MTLPredefinedTransformerAdditions.h"
#import "MTLJSONAdapter.h"
#import "MTLModel.h"
#import "MTLValueTransformer.h"
NSString * const MTLURLValueTransformerName = @"MTLURLValueTransformerName";
NSString * const MTLBooleanValueTransformerName = @"MTLBooleanValueTransformerName";
@implementation NSValueTransformer (MTLPredefinedTransformerAdditions)
#pragma mark Category Loading
+ (void)load {
@autoreleasepool {
MTLValueTransformer *URLValueTransformer = [MTLValueTransformer
reversibleTransformerWithForwardBlock:^ id (NSString *str) {
if (![str isKindOfClass:NSString.class]) return nil;
return [NSURL URLWithString:str];
}
reverseBlock:^ id (NSURL *URL) {
if (![URL isKindOfClass:NSURL.class]) return nil;
return URL.absoluteString;
}];
[NSValueTransformer setValueTransformer:URLValueTransformer forName:MTLURLValueTransformerName];
MTLValueTransformer *booleanValueTransformer = [MTLValueTransformer
reversibleTransformerWithBlock:^ id (NSNumber *boolean) {
if (![boolean isKindOfClass:NSNumber.class]) return nil;
return (NSNumber *)(boolean.boolValue ? kCFBooleanTrue : kCFBooleanFalse);
}];
[NSValueTransformer setValueTransformer:booleanValueTransformer forName:MTLBooleanValueTransformerName];
}
}
#pragma mark Customizable Transformers
+ (NSValueTransformer *)mtl_JSONDictionaryTransformerWithModelClass:(Class)modelClass {
NSParameterAssert([modelClass isSubclassOfClass:MTLModel.class]);
NSParameterAssert([modelClass conformsToProtocol:@protocol(MTLJSONSerializing)]);
return [MTLValueTransformer
reversibleTransformerWithForwardBlock:^ id (id JSONDictionary) {
if (JSONDictionary == nil) return nil;
NSAssert([JSONDictionary isKindOfClass:NSDictionary.class], @"Expected a dictionary, got: %@", JSONDictionary);
return [MTLJSONAdapter modelOfClass:modelClass fromJSONDictionary:JSONDictionary error:NULL];
}
reverseBlock:^ id (id model) {
if (model == nil) return nil;
NSAssert([model isKindOfClass:MTLModel.class], @"Expected a MTLModel object, got %@", model);
NSAssert([model conformsToProtocol:@protocol(MTLJSONSerializing)], @"Expected a model object conforming to <MTLJSONSerializing>, got %@", model);
return [MTLJSONAdapter JSONDictionaryFromModel:model];
}];
}
+ (NSValueTransformer *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass {
NSValueTransformer *dictionaryTransformer = [self mtl_JSONDictionaryTransformerWithModelClass:modelClass];
return [MTLValueTransformer
reversibleTransformerWithForwardBlock:^ id (NSArray *dictionaries) {
if (dictionaries == nil) return nil;
NSAssert([dictionaries isKindOfClass:NSArray.class], @"Expected an array of dictionaries, got: %@", dictionaries);
NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictionaries.count];
for (id JSONDictionary in dictionaries) {
if (JSONDictionary == NSNull.null) {
[models addObject:NSNull.null];
continue;
}
NSAssert([JSONDictionary isKindOfClass:NSDictionary.class], @"Expected a dictionary or an NSNull, got: %@", JSONDictionary);
id model = [dictionaryTransformer transformedValue:JSONDictionary];
if (model == nil) continue;
[models addObject:model];
}
return models;
}
reverseBlock:^ id (NSArray *models) {
if (models == nil) return nil;
NSAssert([models isKindOfClass:NSArray.class], @"Expected an array of MTLModels, got: %@", models);
NSMutableArray *dictionaries = [NSMutableArray arrayWithCapacity:models.count];
for (id model in models) {
if (model == NSNull.null) {
[dictionaries addObject:NSNull.null];
continue;
}
NSAssert([model isKindOfClass:MTLModel.class], @"Expected an MTLModel or an NSNull, got: %@", model);
NSDictionary *dict = [dictionaryTransformer reverseTransformedValue:model];
if (dict == nil) continue;
[dictionaries addObject:dict];
}
return dictionaries;
}];
}
+ (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary {
return [self mtl_valueMappingTransformerWithDictionary:dictionary defaultValue:nil reverseDefaultValue:nil];
}
+ (NSValueTransformer *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary defaultValue:(id)defaultValue reverseDefaultValue:(id)reverseDefaultValue {
NSParameterAssert(dictionary != nil);
NSParameterAssert(dictionary.count == [[NSSet setWithArray:dictionary.allValues] count]);
return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(id<NSCopying> key) {
return dictionary[key ?: NSNull.null] ?: defaultValue;
} reverseBlock:^(id object) {
__block id result = nil;
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id anObject, BOOL *stop) {
if ([object isEqual:anObject]) {
result = key;
*stop = YES;
}
}];
return result ?: reverseDefaultValue;
}];
}
@end