如何在Objective-C中在运行时创建协议?

时间:2010-04-11 01:37:41

标签: objective-c protocols objective-c-runtime

首先,我想清楚我不是在谈论定义协议,而是我理解

的概念
@protocol someprotocol
- (void)method;
@end

我知道Obj-C runtime允许在RUNTIME创建类,以及它的ivars和方法。也可用于创建SEL-s。我想我只是遗漏了一些东西,但有没有人知道在运行时调用什么函数来创建协议?这个的主要原因是conformsToProtocol:工作,所以只是添加适当的方法并没有真正削减它。

2 个答案:

答案 0 :(得分:8)

在运行时添加协议的方法

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)];
}

但委托方法必须事先在该类上定义,否则会因无法识别的选择器而崩溃

或者可以在运行时添加方法.. 然后它会正常工作..

但必须首先导入以下文件。

#include <objc/runtime.h>

答案 1 :(得分:1)

以下类型的作品,但正确这样做的方式将非常感激:

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")));

第一个NSLog参数是1,并不是在将类添加到该类的行被注释掉时,意味着协议 以某种方式向该类注册。另一方面,它不会被objc_getProtocol返回(记录的第二件事是nil)。