Как создать протокол во время выполнения в Objective-C?

Прежде всего, я хочу прояснить, что я не говорю об определении протокола и что я понимаю концепцию

@protocol someprotocol
- (void)method;
@end

Я знаю, что среда выполнения Obj-C позволяет создавать классы во время выполнения, а также их переменные и методы. Также доступны для создания SEL-ы. Я думаю, что просто что-то упускаю, но кто-нибудь знает, какую функцию вызывать для создания протокола во время выполнения? Основная причина этого заключается в том, что конформстопротокол: работает, поэтому простое добавление соответствующих методов на самом деле не помогает.


person Jared Pochtar    schedule 11.04.2010    source источник
comment
Я не думаю, что вы можете. Но что вы собираетесь использовать вновь динамически сгенерированный протокол, если это возможно? Зачем вам нужно тестировать класс на динамически сгенерированном протоколе?   -  person Yuji    schedule 11.04.2010
comment
я пишу интерпретатор Objective-C :D   -  person Jared Pochtar    schedule 11.04.2010
comment
Не уверен, когда я буду использовать это, но это точно было бы аккуратно.   -  person Jonathan Sterling    schedule 04.12.2010


Ответы (2)


Способ добавления протокола во время выполнения

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>
person Exploring    schedule 14.12.2012

следующий вид работы, но правильный способ сделать это был бы очень признателен:

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

person Jared Pochtar    schedule 11.04.2010