如何在运行时使用 Objective-C 动态创建选择器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/112643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 20:46:04  来源:igfitidea点击:

How can I dynamically create a selector at runtime with Objective-C?

objective-ccocoadynamic

提问by craigb

I know how to create a SELat compile time using @selector(MyMethodName:)but what I want to do is create a selector dynamically from an NSString. Is this even possible?

我知道如何SEL在编译时使用创建一个,@selector(MyMethodName:)但我想做的是从NSString. 这甚至可能吗?

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:)语法的方法。

回答by Torsten Marek

I'm not an Objective-C programmer, merely a sympathizer, but maybe NSSelectorFromStringis what you need. It's mentioned explicity in the Runtime Referencethat you can use it to convert a string to a selector.

我不是一个 Objective-C 程序员,只是一个同情者,但也许NSSelectorFromString是你所需要的。在运行时参考中明确提到您可以使用它来将字符串转换为选择器。

回答by Josh Gagnon

According to the XCode documentation, your psuedocode basically gets it right.

根据 XCode 文档,您的伪代码基本上是正确的。

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(aBuffer);

Edit: Bummer, too slow. :P

编辑:无赖,太慢了。:P

回答by Alex Gray

I'd have to say that it's a little more complicatedthan 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)methodArg];

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

and then you need to generate the IMPblock dynamically, this time, passing, "self", the SEL, and any arguments...

然后你需要IMP动态生成块,这一次,传递“self”、theSEL和任何参数......

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)

并将其添加到您的类中,以及整个吸盘的准确方法签名(在这种情况下"v@:@",无效返回,对象调用者,对象参数)

 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.

你可以在我的一个仓库中看到这种运行时恶作剧的一些很好的例子,这里。

回答by Krypton

I know this has been answered for long ago, but still I wanna share. This can be done using sel_registerNametoo.

我知道很久以前就已经回答了这个问题,但我仍然想分享。这也可以使用sel_registerName

The example code in the question can be rewritten like this:

问题中的示例代码可以这样重写:

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