1

Presume I have an Object, an instance of MyClass. In Objective-C one can ask the Object to "perform" a selector by either sending it a message or using NSObject's "perform".

This selector has to be defined at compile time as part of the Class definition, more precisely as an Instance method of that class OR with the help of the Obj-C Runtime, have the method added to the (entire) MyClass at runtime with class_addMethod.

My question is as follows:

Would it be possible to send an object the IMP and ask it to execute it on itself? Essentially I want Objects, different instances of MyClass to execute things on themselves without the entire MyClass knowing about it. Essentially I would call these "per Object methods", an Object1 gets this IMP executed on itself then another Object2 gets a different IMP, and so on. These IMPs are stored somewhere else and it's that Object that knows and decides where to send things.

Lebyrt
  • 1,376
  • 1
  • 9
  • 18
unom
  • 11,438
  • 4
  • 34
  • 54
  • 1
    What exactly are you trying to accomplish here? This sounds like a pretty large hack that might end up being a band-aid when the actual solution is much simpler. – Richard J. Ross III Apr 12 '14 at 12:29
  • To be even more precise, at runtime I have this Instance of a ContextClass and inside one of it's methods I have variables that I use inside a couple of blocks. I want to send these blocks(they automatically take the variable references from the current scope) generate an IMP from them and then send these IMPs from the Context Instance to other Objects to execute on themselves, essentially making the the Object aware of other Objects in the Context through these blocks. The Object should perform this IMP on itself as if I called [self anonymousMethod] on it. Let me know if you got it! – unom Apr 13 '14 at 20:31

2 Answers2

0

yes that works

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface DonorTemplateClass : NSObject
- (void)testMethod:(NSString*)aStringAsParameter;
@end
@implementation DonorTemplateClass
- (void) testMethod:(NSString*)aStringAsParameter {
    NSLog(@"%@ :: %@", self.class, aStringAsParameter);
}
@end

@interface AClass : NSObject
@end
@implementation AClass
@end

@interface AnotherClass : NSObject
@end
@implementation AnotherClass
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        SEL justTheMethodSelector = @selector(testMethod:);
        IMP justTheMethodImplementation = class_getMethodImplementation([DonorTemplateClass class], justTheMethodSelector);

        AClass *anAClassInstance = [[AClass alloc] init];
        AnotherClass *anotherClassInstance = [[AnotherClass alloc] init];

        NSString *aString = @"Test1";

        typedef void (*MyTypeName)(id,SEL, NSString*); // more info about the block syntax on http://goshdarnblocksyntax.com scroll down to "typedef"
        MyTypeName blockName = (MyTypeName)justTheMethodImplementation;

        blockName(anAClassInstance, justTheMethodSelector, aString);
        blockName(anotherClassInstance, justTheMethodSelector, aString);
    }
}

NOTE that I cast my IMP to a typedef'd pointer type. it compiles fine when I just call I but objc_retain crashes then for me ... so I'd say you need to typedef your IMPs before using them but then you can execute them in the context of any suitable class

Daij-Djan
  • 49,552
  • 17
  • 113
  • 135
  • also be aware that while you can ANY class to your implementation, if the implementation access specific member variables of the class itself, it can break – Daij-Djan Apr 12 '14 at 11:10
  • Loved your example but it is very succinct. Could you/I edit it to make it more verbose? If helps if since syntax is rather strange for these things. – unom Apr 13 '14 at 20:43
  • To be even more precise, at runtime I have this Instance of a ContextClass and inside one of it's methods I have variables that I use inside a couple of blocks. I want to send these blocks(they automatically take the variable references from the current scope) generate an IMP from them and then send these IMPs from the Context Instance to other Objects to execute on themselves, essentially making the the Object aware of other Objects in the Context through these blocks. The Object should perform this IMP on itself as if I called [self anonymousMethod] on it. Let me know if you got it! – unom Apr 13 '14 at 20:44
  • Great! The code is more expressive now. Thanks again for the solution. – unom Apr 16 '14 at 09:14
0

IMP is just a typedef for a regular C function pointer. It's meant to point to method implementations, which are C functions with first parameter being an object, and second parameter being a selector. And "an Object to execute an IMP" simply means to call the C function, passing the object as first argument, and a selector as second.

You said you want to be able to "send an object the IMP and ask it to execute it on itself" (i.e. call the IMP passing the object and a selector), yet you do not want "the entire MyClass knowing about it" (which I take to mean you do not want it as a method).

So basically, that sounds like you just want a bunch of standalone C functions, not methods, which you can call, passing various objects, as needed. And you can store these C function pointers as you like. Is that right?

newacct
  • 119,665
  • 29
  • 163
  • 224
  • Yes. You got the picture right. To be even more precise, at runtime I have this Instance of a ContextClass and inside one of it's methods I have variables that I use inside a couple of blocks. I want to send these blocks(they automatically take the variable references from the current context) generate an IMP from them and then send these IMPs from the Context Instance to other Objects to execute on themselves, essentially making the Objects aware of other Objects in the Context through these blocks. Let me know if you got it! – unom Apr 13 '14 at 20:23