Objective-C - Is there a way for an Object to execute a method IMP directly as if it were its own?

夙愿已清 提交于 2020-01-03 03:54:17

问题


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.


回答1:


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




回答2:


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?



来源:https://stackoverflow.com/questions/23029297/objective-c-is-there-a-way-for-an-object-to-execute-a-method-imp-directly-as-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!