Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Fast Reflection for Value Types

DZone's Guide to

Fast Reflection for Value Types

Reflection is sometimes a necessary evil, so here's a way to take the sting out of the tail.

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

A 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

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:
ios ,objective c

Published at DZone with permission of Josh Anderson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}