93

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

我可以做什么:

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

我想做什么:(伪代码,这显然行不通)

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

我一直在搜索 Apple API 文档,但没有找到不依赖编译时@selector(myTarget:)语法的方法。

4

4 回答 4

180

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

于 2008-09-22T00:34:43.403 回答
40

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

在编译时使用 @selector() 指令为 SEL 变量赋值是最有效的。但是,在某些情况下,程序可能需要在运行时将字符串转换为选择器。这可以通过 NSSelectorFromString 函数来完成:

setWidthHeight = NSSelectorFromString(aBuffer);

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

于 2008-09-22T00:42:32.433 回答
13

我不得不说它比以前的受访者的答案可能暗示的要复杂一些......如果你真的想创建一个选择器......而不仅仅是“打电话”你“已经铺设”...... .

您需要创建一个将由您的“新”方法调用的函数指针。所以对于像这样的方法[self theMethod:(id)methodArg];,您将编写...

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

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

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

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

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

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

于 2014-02-01T05:52:10.330 回答
5

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

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

SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];
于 2014-02-26T05:11:16.633 回答