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

StackOverflow https://stackoverflow.com/questions/112643

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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

Это было полезно?

Решение

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

Другие советы

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

Наиболее эффективно присваивать значения переменным 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, вызывающий объект, аргумент объекта)

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

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

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

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

SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top