5

I am trying this method found in Obj-c runtime reference

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

I want to add a new method like:

- [AClass drawWithFrame:(NSRect)rect inView:(id)view]

So far I have written a C function:

void drawWithFrameInView(id this, SEL this_cmd, NSRect frame, id view){
...
} 

now I am ready to do:

BOOL success = class_addMethod(NSClassFromString(@"AClass"), 
                               @selector(drawWithFrame:inView:), 
                               (IMP)drawWithFrameInView, 
                               "v@:@:@:");

but success is never YES, I have tried the same approach with methods with simpler signatures and it worked. So I think the problem is last parameter: "v@:@:@:"

What should I pass in this case to get my new method working ?

2
  • Why not name the first two arguments self and _cmd, so you can write the same code you would have written in a method? Commented Jul 25, 2011 at 11:20
  • Hummm ... just for an aesthetic reason. From the C point of view self and _cmd are supposed to be normal parameters. I didn't like the fact that a parameter was colored as keywords in Obj-C (even though they represent those keywords). That is all :) Commented Jul 25, 2011 at 14:37

1 Answer 1

8

This will work:

char *types = [[NSString stringWithFormat:@"v@:%s@", @encode(NSRect)] UTF8String];

BOOL success = class_addMethod(NSClassFromString(@"MyClass"), 
                               @selector(drawWithFrame:inView:), 
                               (IMP)drawWithFrameInView, 
                               types);

The reason why your code doesn't work is because NSRect is not an object, it is a typedef to a struct.

Learn more about type encodings here.

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

5 Comments

That seems to work (at least I got success = YES :) ). However the docs says: Since the function must take at least two arguments—self and _cmd, the second and third characters must be “@:” (the first character is the return type) and types does not contain a return type, is this because is void or there is some kind of inference here?
@nacho4d types does contain a return type - the first element is 'v', for void.
I'm disappointed that @encode(…) isn't considered a literal. If it were, you could concatenate them at compile time: static const char types[] = @encode(void) @encode(id) @encode(SEL) @encode(NSRect) @encode(id);
@Peter Agreed - even better would be if @encode were a variadic function: @encode(void, id, SEL, NSRect, id);
@Peter that sounds like a great feature request... :)

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.