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

3

首先,我想明确表示我不是在谈论定义协议的问题,并且我理解

@protocol someprotocol
- (void)method;
@end

我知道 Obj-C runtime允许在运行时创建类,以及它的实例变量和方法。还可以创建SEL。我想我只是缺少了某些东西,但有人知道在运行时调用哪个函数来创建协议吗?主要原因是为了使conformsToProtocol:起作用,所以仅添加适当的方法并不真正奏效。

1
我认为你做不到。但是如果可能的话,你打算使用一个新动态生成的协议吗?为什么需要针对一个动态生成的协议测试一个类? - Yuji
3
我正在编写一个 Objective-C 解释器 :D - Jared Pochtar
不确定何时会用到这个,但它肯定有点儿酷。 - Jonathan Sterling
2个回答

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

以下的排序方式是可行的,但如果有一个合适的方法来完成此操作,将不胜感激:

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)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接