如何在Objective-C中创建一个协议?

时间:2022-09-07 11:12:26

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.

我知道object - c运行时允许在运行时创建类,以及它的ivars和方法。也可用于创建的SEL-s。我想我漏掉了一些东西,但是有人知道在运行时调用什么函数来创建协议吗?这样做的主要原因是conformsToProtocol:工作,所以仅仅添加适当的方法并不能真正解决问题。

2 个解决方案

#1


8  

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>

#2


1  

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

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

#1


8  

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>

#2


1  

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

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