Fix incorrect type transformation when the destination class is a mutable class. fixes #1201

This commit is contained in:
Blake Watters
2013-03-09 23:03:06 -05:00
parent 1c2cdc4eef
commit de5aed6bde
3 changed files with 33 additions and 0 deletions

View File

@@ -65,6 +65,19 @@ static BOOL RKIsManagedObject(id object)
return managedObjectClass && [object isKindOfClass:managedObjectClass];
}
/**
NOTE: Because most Foundation classes are implemented as class-clusters, we cannot introspect them for mutability. Instead, we evaluate the destination type and if it is a mutable class, we return `YES` to trigger an invocation of `mutableCopy`.
*/
static BOOL RKIsMutableTypeTransformation(id value, Class destinationType)
{
if ([destinationType isEqual:[NSMutableArray class]]) return YES;
else if ([destinationType isEqual:[NSMutableDictionary class]]) return YES;
else if ([destinationType isEqual:[NSMutableString class]]) return YES;
else if ([destinationType isEqual:[NSMutableSet class]]) return YES;
else if ([destinationType isEqual:[NSMutableOrderedSet class]]) return YES;
else return NO;
}
id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransformer *dateToStringValueTransformer);
id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransformer *dateToStringValueTransformer)
{
@@ -78,6 +91,8 @@ id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransform
} else if (RKClassIsCollection(destinationType) && !RKObjectIsCollection(value)) {
// Call ourself recursively with an array value to transform as appropriate
return RKTransformedValueWithClass(@[ value ], destinationType, dateToStringValueTransformer);
} else if (RKIsMutableTypeTransformation(value, destinationType)) {
return [value mutableCopy];
} else if ([sourceType isSubclassOfClass:[NSString class]] && [destinationType isSubclassOfClass:[NSDate class]]) {
// String -> Date
return [dateToStringValueTransformer transformedValue:value];

View File

@@ -1429,6 +1429,23 @@
assertThat(user.favoriteColors, is(equalTo(@[ @"Blue" ])));
}
- (void)testMappingArrayToMutableArray
{
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[mapping addAttributeMappingsFromDictionary:@{ @"favoriteColors": @"mutableFavoriteColors" }];
NSDictionary *dictionary = @{ @"favoriteColors": @[ @"Blue", @"Red" ] };
RKTestUser *user = [RKTestUser user];
RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:dictionary destinationObject:user mapping:mapping];
RKObjectMappingOperationDataSource *dataSource = [RKObjectMappingOperationDataSource new];
operation.dataSource = dataSource;
NSError *error = nil;
[operation performMapping:&error];
assertThat(user.mutableFavoriteColors, is(equalTo(@[ @"Blue", @"Red" ])));
assertThat(user.mutableFavoriteColors, is(instanceOf([NSMutableArray class])));
}
- (void)testMappingASingularValueToASet
{
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];

View File

@@ -23,6 +23,7 @@
@property (nonatomic, strong) NSDate *birthDate;
@property (nonatomic, strong) NSDate *favoriteDate;
@property (nonatomic, strong) NSArray *favoriteColors;
@property (nonatomic, strong) NSMutableArray *mutableFavoriteColors;
@property (nonatomic, strong) NSDictionary *addressDictionary;
@property (nonatomic, strong) NSURL *website;
@property (nonatomic, strong) NSNumber *isDeveloper;