8

I'm trying to support newly added methods of NSColor in 10.9 on older systems. Pre-10.9 I had these in a category which allowed my to unify code between Mac and iOS. Now that 10.9 has these methods, I get odd drawing wherever I use them. I want to add these methods dynamically to older runtimes and I've found several references for how to do it using class_addMethod. The problem is, that even though addMethod returns success, the methods aren't called.

NSColor *
fColorWithWhite(id self, SEL _cmd, float white, float alpha) {
    return [NSColor colorWithDeviceWhite: white
                                   alpha: alpha];
}

NSColor *
fColorWithRedGreenBlue(id self, SEL _cmd, float red, float green, float blue, float alpha) {
    return [NSColor colorWithDeviceRed: red
                                 green: green
                                  blue: blue
                                 alpha: alpha];
}

+ (void)addLegacySupport {
    Class class = NSClassFromString(@"NSColor");

    BOOL success = class_addMethod(class, @selector(colorWithWhite:alpha:), (IMP)fColorWithWhite, "@@:ff");
    NSLog(@"colorWithWhite:alpha: - %i", success);

    success = class_addMethod(class, @selector(colorWithRed:green:blue:alpha:), (IMP)fColorWithRedGreenBlue, "@@:ffff");
    NSLog(@"colorWithRed:green:blue:alpha: - %i", success);
}

Any pointers would be much appreciated.

2 Answers 2

6

You are trying to add class methods. You need to add them to the metaclass.

Class meta_cls = objc_getMetaClass("NSColor");
Sign up to request clarification or add additional context in comments.

2 Comments

This looked so amazing that I couldn't believe I didn't see it in the API docs but also returned false on class_addMethod.
Solved: The above worked. The underlying problem had to do with casting of double to CGFloat to a float.
6

class_addMethod() adds an instance method to the class. You are trying to add a class method. Thus, you need to add the method to the metaclass (classes are instances of their metaclasses), which you can get by calling object_getClass() with the class as the argument:

Class metaclass = object_getClass(NSClassFromString(@"NSColor"));

BOOL success = class_addMethod(metaclass, @selector(colorWithWhite:alpha:), (IMP)fColorWithWhite, "@@:ff");

3 Comments

No success. class_addMethod returns false.
Huh. It's working here. What SDK are you testing against? It'll fail if the method already exists (i.e., on 10.9).
I am building against 10.8 so that I actually see the errors and don't have the code backing. I don't have a pre 10.9 system to run on at the moment, so this seemed like my best bet for testing this successfully before releasing.

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.