Как я могу динамически создать селектор во время выполнения с 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];