Re: Abstracting a group of commonly named Selectors


Jeff Laing
 

In the designated initialise of your Parser class, you can use class_addMethod to add whatever you like to your instance's class.

https://developer.apple.com/documentation/objectivec/1418901-class_addmethod?language=objc

The method implementation gets called with the selector as its second argument and you can cut the string up at runtime to then call your Parse. Here's a snippet from an app I did in the past that wanted to dynamically adjust to any entries that were added to a popup menu in Interface Builder. It iterates over the popup, and for every entry present, looks for then adds a dynamic method called _popup.

        IMP popup_imp = class_getMethodImplementation([self class], @selector(_popup00:));
...
        for (NSArray *item in popup) {
                // make sure that we implement the required method
                SEL sel = NSSelectorFromString([NSString stringWithFormat:@"_popup%02ld:",(long)[menuItems count]]);
                if (![self respondsToSelector:sel]) {
                        class_addMethod([self class], sel, popup_imp, "v@:@");  // -(void)method:(id)argument;
                }

The implementation of the method gets the name of the selector using set_getName, then punts across to the actual code.

- (void)_popup00:(id)sender {
//          01234567
        const char *name = sel_getName(_cmd);
        const int idx = atoi(name+6);
        id resp = [self.popupResponders objectAtIndex:idx];
        [resp callWithArrayOfArgs:self.popupArguments];
}

Extracting your specific token from the message is just name+. This example is using (void) but it should work just fine - you aren't using the "no such method" path, you are just binding the method really late in the compile/link/run process...

Join {cocoa@apple-dev.groups.io to automatically receive all group messages.