@selector
is not a method, it is a, well, selector, which helps the Objective C runtime select a method. Methods in Objective C are C functions with at least two parameters, which are required: id self
, which represents the object and SEL selector
which represents the selector that was used to call the function. If the method was defined with more parameters, they come after the two mandatory parameters. This function is called an IMP
, implementation. Each Objective C method has a backing IMP
.
IMP
is defined like so:
typedef id (*IMP)(id, SEL, ...);
If you have a C function, and it has the correct parameter layout, you can assign that function to an existing, or entirely new method, and add to a class as an instance or class method. If your C function does not have the required parameter layout, you are looking at a crash. Make sure the C function is correct.
So let's assume the C function:
void func_name(id self, SEL sel, NSUInteger x)
{
NSLog(@"I was called on object %@ with selector %@ and argument %lu", self, NSStringFromSelector(sel), x);
}
And wish to assign it to -[NSObject myNewMethodWithUnsignedInteger:]
, you would do it like so using the runtime:
class_addMethod([NSObject class], @selector(myNewMethodWithUnsignedInteger:), (IMP)func_name, [NSString stringWithFormat:@"v@:%s", @encode(NSUInteger)]);
Make sure to read the documentation of class_addMethod
here.
If your C function is not in the required format, you can use imp_implementationWithBlock
to wrap the call of your function inside a block.
So let's assume you have the following function:
void nonCompliantFunc(NSUInteger x)
{
NSLog(@"Can't touch this!");
}
You could add it as a method like so:
IMP imp = imp_implementationWithBlock(^ (id self, NSUInteger x) { nonCompliantFunc(x); };
class_addMethod([NSObject class], @selector(myNewMethodWithUnsignedInteger:), imp, [NSString stringWithFormat:@"v@:%s", @encode(NSUInteger)]);
You should check the return value of class_addMethod
to make sure the method was added successfully.
To answer your update, selectors are pointers, but they are pointers in a method table. All selectors are collected when the runtime is loaded, and a table is built. Then, when each class is loaded, a method table is set up, pairing selector and implementation. This is a lot more complex, but this is the gist of it.
The pointer you are thinking of is the one obtained using method_getImplementation()
, but you cannot pass that instead of selectors.