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

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

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

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

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

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

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

Ответ 1

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

Ответ 2

В соответствии с документацией XCode ваш psuedocode в основном исправляет его.

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

setWidthHeight = NSSelectorFromString(aBuffer);

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

Ответ 3

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

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

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

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

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

и добавьте его в свой класс вместе с точной сигнатурой метода для всей присоски (в данном случае "[email protected]:@", void return, object caller, object object)

 class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "[email protected]:@");

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

Ответ 4

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

Пример кода в вопросе можно переписать следующим образом:

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