Wednesday, 18 September 2013

Invoking Method on Object causing error Obj-C

Invoking Method on Object causing error Obj-C

In my code I take an object, dynamically create a new class make that new
class subclass from the objects class and dynamically set the object's
class to this new class.
I made it so that every method call runs some code as I implement the
methods. However I then try to invoke/forward the method onto the original
class. But I have no luck.
Is their anyway to do this?
Here is my code
//Register Object For Verification
void register_object_for_verification(id object){
Class objectClass = object_getClass(object);
char * objectClassName = (char *)class_getName(objectClass);
char * proxyClassPrefix = "Proxied_";
char * proxyClassName = malloc(strlen(objectClassName) +
strlen(proxyClassPrefix) + 1);
if(proxyClassName == NULL) {
//out of memory
return;
}
strcat(proxyClassName, proxyClassPrefix);
strcat(proxyClassName, objectClassName);
Class proxyClass = objc_lookUpClass((const char *)proxyClassName);
NSLog(@"Creating Proxy Class %s", proxyClassName);
if (!proxyClass) {
NSLog(@"Attaching Proxy Class");
proxyClass = objc_allocateClassPair(objectClass, (const char
*)proxyClassName, 0);
SEL methodSignatureSelector = @selector(methodSignatureForSelector:);
Method methodSignatureMethod = class_getInstanceMethod(objectClass,
methodSignatureSelector);
int unsigned numMethods;
Method * objectMethods = class_copyMethodList(objectClass, &numMethods);
for (int i = 0; i < numMethods; i++) {
Method method = objectMethods[i];
SEL methodSelector = method_getName(method);
if ( methodSelector != @selector(class) || methodSelector ==
@selector(superclass) || methodSelector ==
methodSignatureSelector){
class_addMethod(proxyClass, methodSelector,
(IMP)verify_object, method_getTypeEncoding(method));
}
}
class_addMethod(proxyClass, methodSignatureSelector,
(IMP)proxy_method_signature,
method_getTypeEncoding(methodSignatureMethod));
objc_registerClassPair(proxyClass);
object_setClass(object, proxyClass);
}
}
//Proxies the method siganture
id proxy_method_signature(id self, SEL _cmd, SEL _selector){
NSLog(@"Proxying Method Signature for %s", sel_getName(_selector));
//Create Super Struct needed to proxy message
struct objc_super super = {self, class_getSuperclass([self class])};
//Forward method signature request
NSMethodSignature * result = (NSMethodSignature
*)objc_msgSendSuper(&super, _cmd, _selector);
NSLog(@"Number of arguments %i", [result numberOfArguments]);
NSLog(@"Method Return Type %s", [result methodReturnType]);
return result;
}
//Verify Security Object
id verify_object(id self, SEL _cmd, ...){
Class objectClass = object_getClass(self);
Class super = class_getSuperclass(objectClass);
NSLog(@"Verifying [%s %s]", class_getName(objectClass), sel_getName(_cmd));
//Verfication Code Goes Here
NSInvocation *invocation = [NSInvocation
invocationWithMethodSignature:[self methodSignatureForSelector:_cmd]];
[invocation setSelector:_cmd];
[invocation setTarget:self];
va_list args;
va_start(args, _cmd);
Method objectMethod = class_getInstanceMethod(super, _cmd);
int numberOfArgs = method_getNumberOfArguments(objectMethod);
for (NSUInteger i = 0; i < numberOfArgs; i++) {
id arg = va_arg( args, id);
[invocation setArgument:&arg atIndex:i];
}
[invocation invoke];
va_end(args);
id ret;
[invocation getReturnValue:&ret];
return ret;
}

No comments:

Post a Comment