Skip to content

Commit

Permalink
Huge performance improvement, specially in cases where not all key va…
Browse files Browse the repository at this point in the history
…lues are mapped from dictionary to properties
  • Loading branch information
Aryan Ghassemi committed Dec 13, 2013
1 parent bf17756 commit 25ac2c0
Showing 1 changed file with 58 additions and 27 deletions.
85 changes: 58 additions & 27 deletions OCMapper/Source/ObjectMapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

@interface ObjectMapper()
@property (nonatomic, strong) NSMutableArray *commonDateFormaters;
@property (nonatomic, strong) NSMutableArray *classNamesInMainBundle;
@property (nonatomic, strong) NSMutableDictionary *mappedClassNames;
@end

@implementation ObjectMapper
Expand All @@ -62,6 +64,16 @@ + (ObjectMapper *)sharedInstance
return singleton;
}

- (id)init
{
if (self = [super init])
{
[self populateClassNamesInMainBundle];
}

return self;
}

#pragma mark - Public Methods -

- (id)objectFromSource:(id)source toInstanceOfClass:(Class)class
Expand Down Expand Up @@ -103,6 +115,36 @@ - (id)dictionaryFromObject:(NSObject *)object

#pragma mark - Private Methods -

- (void)populateClassNamesInMainBundle
{
self.classNamesInMainBundle = [NSMutableArray array];

int numClasses;
Class *classes = NULL;

classes = NULL;
numClasses = objc_getClassList(NULL, 0);

if (numClasses > 0)
{
classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);

for (int i = 0; i < numClasses; i++)
{
@autoreleasepool
{
Class class = classes[i];

if ([NSBundle bundleForClass:class] == [NSBundle mainBundle])
[self.classNamesInMainBundle addObject:NSStringFromClass(class)];
}
}
}

free(classes);
}

- (NSArray *)processDictionaryFromArray:(NSArray *)array
{
NSMutableArray *result = [NSMutableArray array];
Expand Down Expand Up @@ -215,13 +257,13 @@ - (id)processDictionary:(NSDictionary *)source forClass:(Class)class
{
propertyName = [self.instanceProvider propertyNameForObject:object byCaseInsensitivePropertyName:key];

if ([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]])
if (propertyName && ([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]]))
{
objectType = [self classFromString:key];
}
}

if (class && object && [object respondsToSelector:NSSelectorFromString(propertyName)])
if (class && object && propertyName && [object respondsToSelector:NSSelectorFromString(propertyName)])
{
ILog(@"Mapping key(%@) to property(%@) from data(%@)", key, propertyName, [value class]);

Expand Down Expand Up @@ -287,7 +329,10 @@ - (id)processArray:(NSArray *)value forClass:(Class)class

- (Class)classFromString:(NSString *)className
{
Class result = nil;
Class result = [self.mappedClassNames objectForKey:className];

if (result)
return result;

if (NSClassFromString(className))
return NSClassFromString(className);
Expand All @@ -297,35 +342,21 @@ - (Class)classFromString:(NSString *)className

NSString *classNameLowerCase = [className lowercaseString];

int numClasses;
Class *classes = NULL;

classes = NULL;
numClasses = objc_getClassList(NULL, 0);

if (numClasses > 0)
for (NSString *className in self.classNamesInMainBundle)
{
classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);

for (int i = 0; i < numClasses; i++)
@autoreleasepool
{
@autoreleasepool
NSString *thisClassNameLowerCase = [className lowercaseString];

if ([thisClassNameLowerCase isEqual:classNameLowerCase] ||
[[NSString stringWithFormat:@"%@s", thisClassNameLowerCase] isEqual:classNameLowerCase] ||
[[NSString stringWithFormat:@"%@es", thisClassNameLowerCase] isEqual:classNameLowerCase])
{
Class class = classes[i];
NSString *thisClassNameLowerCase = [NSStringFromClass(class) lowercaseString];

if ([thisClassNameLowerCase isEqual:classNameLowerCase] ||
[[NSString stringWithFormat:@"%@s", thisClassNameLowerCase] isEqual:classNameLowerCase] ||
[[NSString stringWithFormat:@"%@es", thisClassNameLowerCase] isEqual:classNameLowerCase])
{
result = class;
break;
}
result = NSClassFromString(className);
[self.mappedClassNames setObject:result forKey:className];
break;
}
}

free(classes);
}

return result;
Expand Down

0 comments on commit 25ac2c0

Please sign in to comment.