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

Я знаю, как создать SEL во время компиляции с использованием @selector(MyMethodName:) но то, что я хочу сделать, это динамически создать селектор из NSString, Это вообще возможно?

Что я могу сделать:

SEL selector = @selector(doWork:);
[myobj respondsToSelector:selector];

Что я хочу сделать: (псевдокод, это, очевидно, не работает)

SEL selector = selectorFromString(@"doWork");
[myobj respondsToSelector:selector];

Я искал документы по API Apple, но не нашел способа, который не зависит от времени компиляции @selector(myTarget:) синтаксис.

4 ответа

Решение

Я не программист Objective-C, просто сочувствующий, но, возможно, NSSelectorFromString - то, что вам нужно. В справочнике по времени выполнения упоминается о простоте, которую вы можете использовать для преобразования строки в селектор.

Согласно документации XCode, ваш psuedocode в основном понимает все правильно.

Наиболее эффективно присваивать значения переменным SEL во время компиляции с помощью директивы @selector(). Однако в некоторых случаях программе может потребоваться преобразовать строку символов в селектор во время выполнения. Это можно сделать с помощью функции NSSelectorFromString:

setWidthHeight = NSSelectorFromString(aBuffer);

Изменить: облом, слишком медленно.:П

Я должен сказать, что это немного сложнее, чем можно предположить из ответов предыдущих респондентов... если вы действительно действительно хотите создать селектор... а не просто "позвонить одному", который у вас "лежит".,

Вам нужно создать указатель на функцию, который будет вызываться вашим "новым" методом.. так что для метода, подобного [self theMethod:(id)methodArg];, ты бы написал...

void (^impBlock)(id,id) = ^(id _self, id methodArg) { 
     [_self doSomethingWith:methodArg]; 
};

а затем вам нужно сгенерировать IMP блокировать динамически, на этот раз, проходя, "я", SEL и любые аргументы...

void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock);

и добавьте его в свой класс вместе с точной сигнатурой метода для всей присоски (в данном случае "v@:@", void return, объект вызывающий, аргумент объекта)

 class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "v@:@");

Вы можете увидеть несколько хороших примеров такого рода махинаций во время выполнения в одном из моих репозиториев здесь.

Я знаю, что на это уже давно дан ответ, но все же хочу поделиться. Это можно сделать с помощью sel_registerName тоже.

Пример кода в вопросе можно переписать так:

SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];
Другие вопросы по тегам