I know how to create a SEL
at compile time using @selector(MyMethodName:)
but what I want to do is create a selector dynamically from an NSString
. Is this even possible?
我知道如何在编译时使用@selector(MyMethodName:)创建一个SEL,但我想做的是从NSString动态创建一个selector。这是可能吗?
What I can do:
我能做什么:
SEL selector = @selector(doWork:);
[myobj respondsToSelector:selector];
What I want to do: (pseudo code, this obviously doesn't work)
我想做的是:(伪代码,这显然行不通)
SEL selector = selectorFromString(@"doWork");
[myobj respondsToSelector:selector];
I've been searching the Apple API docs, but haven't found a way that doesn't rely on the compile-time @selector(myTarget:)
syntax.
我一直在搜索Apple API文档,但还没有找到一种不依赖于编译时@selector(myTarget:)语法的方法。
4 个解决方案
#1
179
I'm not an Objective-C programmer, merely a sympathizer, but maybe NSSelectorFromString is what you need. It's mentioned explicity in the Runtime Reference that you can use it to convert a string to a selector.
我不是一个Objective-C程序员,只是一个同情者,但是NSSelectorFromString可能是你需要的。运行时引用中提到可以使用它将字符串转换为选择器。
#2
40
According to the XCode documentation, your psuedocode basically gets it right.
根据XCode文档,您的psuedocode基本上是正确的。
It’s most efficient to assign values to SEL variables at compile time with the @selector() directive. However, in some cases, a program may need to convert a character string to a selector at runtime. This can be done with the NSSelectorFromString function:
使用@selector()指令在编译时为SEL变量赋值是最有效的。但是,在某些情况下,程序可能需要在运行时将字符串转换为选择器。这可以通过NSSelectorFromString函数来实现:
setWidthHeight = NSSelectorFromString(aBuffer);
setWidthHeight = NSSelectorFromString(在);
Edit: Bummer, too slow. :P
编辑:懒汉,太慢了。:P
#3
9
I'd have to say that it's a little more complicated than the previous respondents' answers might suggest... if you indeed really want to create a selector... not just "call one" that you "have laying around"...
我得说,这比之前受访者的回答要复杂一点……如果你真的想要创建一个选择器…不只是“叫一个”你“在周围”……
You need to create a function pointer that will be called by your "new" method.. so for a method like [self theMethod:(id)methodArg];
, you'd write...
您需要创建一个函数指针,它将被您的“新”方法调用。所以对于像[self theMethod:(id)方法];
void (^impBlock)(id,id) = ^(id _self, id methodArg) {
[_self doSomethingWith:methodArg];
};
and then you need to generate the IMP
block dynamically, this time, passing, "self", the SEL
, and any arguments...
然后您需要动态地生成IMP块,这次,传递,“self”,SEL,以及任何参数……
void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock);
and add it to your class, along with an accurate method signature for the whole sucker (in this case "v@:@"
, void return, object caller, object argument)
并将其添加到类中,并为整个sucker添加一个精确的方法签名(在本例中为“v@:@”、void return、对象调用者、对象参数)
class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "v@:@");
You can see some good examples of this kind of runtime shenanigans, in one of my repos, here.
在我的一个repos中,你可以看到这种运行时诡计的一些很好的例子。
#4
3
I know this has been answered for long ago, but still I wanna share. This can be done using sel_registerName
too.
我知道这已经被回答很久了,但我还是想分享。这也可以使用sel_registerName来完成。
The example code in the question can be rewritten like this:
问题中的示例代码可以这样重写:
SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];
#1
179
I'm not an Objective-C programmer, merely a sympathizer, but maybe NSSelectorFromString is what you need. It's mentioned explicity in the Runtime Reference that you can use it to convert a string to a selector.
我不是一个Objective-C程序员,只是一个同情者,但是NSSelectorFromString可能是你需要的。运行时引用中提到可以使用它将字符串转换为选择器。
#2
40
According to the XCode documentation, your psuedocode basically gets it right.
根据XCode文档,您的psuedocode基本上是正确的。
It’s most efficient to assign values to SEL variables at compile time with the @selector() directive. However, in some cases, a program may need to convert a character string to a selector at runtime. This can be done with the NSSelectorFromString function:
使用@selector()指令在编译时为SEL变量赋值是最有效的。但是,在某些情况下,程序可能需要在运行时将字符串转换为选择器。这可以通过NSSelectorFromString函数来实现:
setWidthHeight = NSSelectorFromString(aBuffer);
setWidthHeight = NSSelectorFromString(在);
Edit: Bummer, too slow. :P
编辑:懒汉,太慢了。:P
#3
9
I'd have to say that it's a little more complicated than the previous respondents' answers might suggest... if you indeed really want to create a selector... not just "call one" that you "have laying around"...
我得说,这比之前受访者的回答要复杂一点……如果你真的想要创建一个选择器…不只是“叫一个”你“在周围”……
You need to create a function pointer that will be called by your "new" method.. so for a method like [self theMethod:(id)methodArg];
, you'd write...
您需要创建一个函数指针,它将被您的“新”方法调用。所以对于像[self theMethod:(id)方法];
void (^impBlock)(id,id) = ^(id _self, id methodArg) {
[_self doSomethingWith:methodArg];
};
and then you need to generate the IMP
block dynamically, this time, passing, "self", the SEL
, and any arguments...
然后您需要动态地生成IMP块,这次,传递,“self”,SEL,以及任何参数……
void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock);
and add it to your class, along with an accurate method signature for the whole sucker (in this case "v@:@"
, void return, object caller, object argument)
并将其添加到类中,并为整个sucker添加一个精确的方法签名(在本例中为“v@:@”、void return、对象调用者、对象参数)
class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "v@:@");
You can see some good examples of this kind of runtime shenanigans, in one of my repos, here.
在我的一个repos中,你可以看到这种运行时诡计的一些很好的例子。
#4
3
I know this has been answered for long ago, but still I wanna share. This can be done using sel_registerName
too.
我知道这已经被回答很久了,但我还是想分享。这也可以使用sel_registerName来完成。
The example code in the question can be rewritten like this:
问题中的示例代码可以这样重写:
SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];