94

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?

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.

4 Answers 4

180

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I need to brush up on my Google-fu. that's exactly what I was (or wasn't as it may be) looking for.
Well, I still had the links flying around in my bookmarks since I've read through the Objective-C 2.0 docs a couple of days ago.
40

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

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:

setWidthHeight = NSSelectorFromString(aBuffer);

Edit: Bummer, too slow. :P

3 Comments

NSStringFromSelector(@"doWork") converts it the other way (just fyi)
I think you mean, NSStringFromSelector(@selector(doWork))
And what does that selector supposedly do? Shouldn't we specify a block or something?
14

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...

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...

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)

 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.

Comments

5

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

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

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

1 Comment

Actually, NSSelectorFromString mentioned by @torsten-marek uses sel_registerName under the hood. appledev: "NSSelectorFromString passes a UTF-8 encoded character representation of aSelectorName to sel_registerName and returns the value returned by that function"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.