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

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

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

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

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

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

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


person craigb    schedule 22.09.2008    source источник


Ответы (4)


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

person Torsten Marek    schedule 22.09.2008
comment
Мне нужно освежить свое гугл-фу. это именно то, что я искал (или не искал, как может быть). - person craigb; 22.09.2008
comment
Ну, у меня все еще были ссылки, летающие в моих закладках, так как я прочитал документацию по Objective-C 2.0 пару дней назад. - person Torsten Marek; 22.09.2008

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

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

setWidthHeight = NSSelectorFromString(aBuffer);

Редактировать: облом, слишком медленно. :П

person Josh Gagnon    schedule 22.09.2008
comment
NSStringFromSelector(@"doWork") преобразует его в другую сторону (просто к вашему сведению) - person bendytree; 30.01.2012
comment
Я думаю, вы имеете в виду NSStringFromSelector(@selector(doWork)) - person jpswain; 23.03.2012
comment
И что этот селектор якобы делает? Разве мы не должны указать блок или что-то в этом роде? - person user4951; 04.11.2012

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

Вам нужно создать указатель функции, который будет вызываться вашим «новым» методом.. поэтому для такого метода, как [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@:@", возврат пустоты, вызывающая сторона объекта, аргумент объекта)

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

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

person Alex Gray    schedule 01.02.2014

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

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

SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];
person Krypton    schedule 26.02.2014
comment
На самом деле, NSSelectorFromString, упомянутый @torsten-marek, использует sel_registerName под капотом. appledev: NSSelectorFromString передает кодировку UTF-8 символьное представление aSelectorName в sel_registerName и возвращает значение, возвращаемое этой функцией - person PLG; 13.02.2018