Fast Reflection for Value Types
Reflection is sometimes a necessary evil, so here's a way to take the sting out of the tail.
Join the DZone community and get the full member experience.
Join For FreeA long while back, I wrote an article on Reflection.
C# to Objective-C - Part 6: Reflection
And the code in that article still holds true. As you know, reflection is really expensive but sometimes a necessary evil. However, it's especially expensive for value types because of boxing and unboxing.
I wrote another article on this topic a while ago as well.
Going From C# To Objective-C: Boxing and Unboxing
Basically, whenever you use reflection, Obj-c takes the value and wraps it in an NSValue object or an NSNumber if you're dealing with a number.
Today, I'm going to show you, how you can actually skip the boxing and unboxing. Although it's a bit tricky, it'll definitely speed up your application if you're using reflection to loop through large amounts of data.
To keep the topic as simple as possible, I'm going to show you how to do this for double's. However, you can customize this to support any other value type, although you'll have to know what value types you're supporting up front.
First we need to typedef a method called "getDouble" that will return our value:
typedef double (*getDouble)(id, SEL);
Next we need to define a block called "helperBlock" that we will invoke for reflection:
typedef double (^helperBlock)(NSObject*, SEL, IMP);
Now we can create an instance of helperBlock
helperBlock block = ^double (NSObject* obj, SEL selector, IMP method)
{
getDouble f = (getDouble)method;
return f(obj, selector);
};
Notice how we're casing the IMP as our getDouble method, so that we know what the return type is.
Let's create a dummy class that we'd use this against:
@interface ObjectToReflect
@property(nonatomic, assign)double value;
@property(nonatomic, assign)NSString* key;
@end
So how would we reflect and get the value property? Well, let's assume we created an array of "ObjectToReflect" objects.
IMP method = nil;
for(NSObject* obj in data)
{
if(method == nil)
method = [obj methodForSelector:getProp];
double val = block(obj, NSSelectorFromString(@“value”), method);
}
And now you've reflected against your data object. Like I said, its a bit complicated, but hopefully this helps simplify things. And it certainly will make your code much faster.
Written by Stephen Zaharuk
Published at DZone with permission of Josh Anderson, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments