代码之家  ›  专栏  ›  技术社区  ›  craigb

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

  •  90
  • craigb  · 技术社区  · 18 年前

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

    我能做什么:

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

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

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

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

    4 回复  |  直到 8 年前
        1
  •  179
  •   PLG    8 年前

    我不是一个客观的C程序员,只是一个同情者,但也许 NSSelectorFromString 是你需要的。这是在 Runtime Reference 可以使用它将字符串转换为选择器。

        2
  •  40
  •   Josh Gagnon Steinar    18 年前

    根据Xcode文档,您的psuedocode基本上是正确的。

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

    setWidthHeight = NSSelectorFromString(aBuffer);

    编辑:很糟糕,太慢了。P

        3
  •  9
  •   Alex Gray    12 年前

    我不得不这么说 有点复杂 比以前的回答可能暗示的…如果你真的想 创建选择器 …不仅仅是“打个电话”,你“在周围躺着”…

    您需要创建一个函数指针,该指针将由“new”方法调用。所以对于像这样的方法 [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);
    

    并将其添加到您的类中,同时为整个吸盘添加精确的方法签名(在本例中 "v@:@" ,void返回,对象调用方,对象参数)

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

    你可以看到一些很好的例子 runtime shenanigans , in one of my repos, here.

        4
  •  3
  •   Krypton    12 年前

    我知道这个问题很久以前就有人回答了,但我还是想分享。这可以用 sel_registerName 也是。

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

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