简体   繁体   中英

How to create a protocol at runtime in Objective-C?

First of all, I want to be clear that I'm not talking about defining a protocol, and that I understand the concept of

@protocol someprotocol
- (void)method;
@end

I know that the Obj-C runtime allows creation of classes at RUNTIME, as well as its ivars and methods. Also available for creation are SEL-s. I think I'm just missing something, but does anyone know what function to call to create a protocol at runtime? The main reason for this is for conformsToProtocol: to work, so just adding the appropriate methods doesn't really cut it.

Way to add protocol at runtime

Protocol *aProtocol = objc_allocateProtocol("TestingRuntimeDelegate");
AppDelegate *appInstance = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSLog(@"conformed Protocol ..%d",class_conformsToProtocol([self.delegate class], aProtocol));

protocol_addMethodDescription(aProtocol, @selector(itIsTestDelegate), "test", NO, NO);
objc_registerProtocol(aProtocol);
class_addProtocol([appInstance class], aProtocol);
//NSLog(@"adding Protocol %d",class_addProtocol([appInstance class], aProtocol));

if ([self.delegate conformsToProtocol:@protocol(TestDelegate)])
{
    NSLog(@"conformed Protocol ..");
}
else
{
    NSLog(@"conformed Protocol ..%d",class_conformsToProtocol([appInstance class], aProtocol));
    class_conformsToProtocol([self.delegate class], aProtocol);
    [appInstance performSelector:@selector(itIsTestDelegate)];
}

But the delegate method must be previously defined on that class otherwise it will crash due to unrecognized selector

or the method can be added at run time.. Then it will work fine..

But the following file must be imported first.

#include <objc/runtime.h>

the following sort of works, but a proper way of doing this would be much appreciated:

Protocol *proto = [Protocol alloc];
object_setInstanceVariable(proto, "protocol_name", &"mySuperDuperProtocol");
void *nada = NULL;
object_setInstanceVariable(proto, "protocol_list", &nada);
object_setInstanceVariable(proto, "class_methods", &nada);

struct objc_method_description_list *methods;
methods = malloc(sizeof(int) + sizeof(struct objc_method_description) * 1);
methods->count = 1;
methods->list[0].name = @selector(foobar:);
methods->list[0].types = "v:@";
object_setInstanceVariable(proto, "instance_methods", &methods);

class_addProtocol([self class], proto);
NSLog(@"%d %s", [self conformsToProtocol:proto], protocol_getName(objc_getProtocol("mySuperDuperProtocol")));

The first NSLog parameter is 1, and isn't when the line adding the protocol to the class is commented out, meaning the protocol is somehow registered with the class. On the other hand, it does not get returned by objc_getProtocol (the second thing logged is nil).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM